You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When specifying the name of a persistence unit to use for LocalContainerEntityManagerFactoryBean (ie., assuming there are multiple persistence units defined in persistence.xml), this name is now applied to the persistence unit from scanned pacakges.
In 3.1.0, the name applied to the generated package was 'default'. However, now, the name applied is the one defined in the entityManager configuration.
This results in an exception "Conflicting persistence unit definitions for name 'xxx'".
This is a breaking change in behaviour from 3.1.0 to 3.1.2.
The change is caused by new setter behaviour introduced in LocalContainerEntityManagerFactoryBean in 3.1.2, specifically this code:
This changes the internal defaultPersistenceUnitName from default. Later, when DefaultPersistenceUnit.buildDefaultPersistenceUnitInfo() is called, a new persistence unit is generated using this name:
We expected the "packagesToScan" property to only be set when actually exposing the default persistence unit in the given LocalContainerEntityManagerFactoryBean...
In your scenario, you seem to be setting a "packagesToScan" entry while nevertheless referring to a pre-defined persistence unit from your persistence.xml file. Aren't you effectively ignoring your scanned packages then, since you're building the default persistence unit that way but subsequently expose your "test" persistence unit instead?
Glad to know that it's a configuration issue on my side.
I'll fix the issue.
However, it is a change in behaviour between versions. Perhaps some documentation could help lost souls like myself? ("Don't combine persistence.xml and 'packagesToScan' properties")
One thought (and I suspect I'm showing my ignorance here)...
We used the packagesToScan approach to work around having scanned @Entity classes in multiple modular jars.
However, we use persistence units primarily to register extensions, such as jadira.usertype.autoRegisterUserType which enables JodaTime and JodaMoney mappings by default.
Attempting to set these properties directly against the org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter caused an error:
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'jadira' of bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Bean property 'jadira' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
This is what lead us to using this combined approach. However, from reading your post, I suspect the config is invalid (which may explain other issues we encountered).
As of Spring 3.1.3, we pick the same-named unit from persistence.xml in case of a conflict with the default persistence unit. This should allow your scenario to keep working as it did against Spring 3.1.0, even if you're effectively ignoring your "packagesToScan" setting that way.
As for provider-specific properties: You can set them on the "jpaProperties" property on LocalContainerEntityManagerFactoryBean itself, through the generic JPA property mechanism. They will be passed through to Hibernate, without a need to touch Spring's HibernateJpaVendorAdapter.
Marty Pitt opened SPR-9741 and commented
When specifying the name of a persistence unit to use for LocalContainerEntityManagerFactoryBean (ie., assuming there are multiple persistence units defined in persistence.xml), this name is now applied to the persistence unit from scanned pacakges.
In 3.1.0, the name applied to the generated package was 'default'. However, now, the name applied is the one defined in the entityManager configuration.
This results in an exception "Conflicting persistence unit definitions for name 'xxx'".
This is a breaking change in behaviour from 3.1.0 to 3.1.2.
The change is caused by new setter behaviour introduced in LocalContainerEntityManagerFactoryBean in 3.1.2, specifically this code:
{{
@Override
public void setPersistenceUnitName(String persistenceUnitName) {
super.setPersistenceUnitName(persistenceUnitName);
this.internalPersistenceUnitManager.setDefaultPersistenceUnitName(persistenceUnitName);
}
}}
This changes the internal defaultPersistenceUnitName from
default
. Later, whenDefaultPersistenceUnit.buildDefaultPersistenceUnitInfo()
is called, a new persistence unit is generated using this name:{{
private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {
SpringPersistenceUnitInfo scannedUnit = new SpringPersistenceUnitInfo();
scannedUnit.setPersistenceUnitName(this.defaultPersistenceUnitName);
scannedUnit.setExcludeUnlistedClasses(true);
}}
This then results in an exception being thrown.
As an example, here's the defined
Persistence.xml
, which contains both a prod config, and a test config:{{
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="production">
<properties>
<!-- JPA Configuration goes here -->
</properties>
</persistence-unit>
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!-- JPA Configuration goes here -->
</properties>
</persistence-unit>
</persistence>
}}
Then, the appropriate config is selected in the EntityManager configration:
{{
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>aa.bb.cc</value>
</list>
</property>
<property name="persistenceUnitName" value="test" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
</bean>
</property>
</bean>
}}
This causes the exception.
Affects: 3.1.2
Reference URL: http://stackoverflow.com/questions/12189921/conflicting-persistence-unit-definitions-when-testing
Referenced from: commits 0cf4a26, f32e407
The text was updated successfully, but these errors were encountered: