Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default PersistenceUnit is configured with wrong name, resulting in duplicates & causes RTE. [SPR-9741] #14375

Closed
spring-projects-issues opened this issue Aug 30, 2012 · 4 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

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, when DefaultPersistenceUnit.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

@spring-projects-issues
Copy link
Collaborator Author

Marty Pitt commented

Any update on this issue?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

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?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Marty Pitt commented

Ah, I see.

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).

Thanks for your help.

Marty

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

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.

Hope that helps,

Juergen

@spring-projects-issues spring-projects-issues added type: bug A general bug in: data Issues in data modules (jdbc, orm, oxm, tx) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.1.3 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants