Browse Source

Make LocalEntityManagerFactoryBean#setDataSource work on Hibernate and EclipseLink

Includes fix for consistent PersistenceException in case of no unit found for name.
Includes proper tests for LocalContainerEntityManagerFactoryBean with scan setup.

Closes gh-36272
6.2.x
Juergen Hoeller 1 month ago
parent
commit
bb35e9f11c
  1. 3
      spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java
  2. 12
      spring-orm/src/main/java/org/springframework/orm/jpa/LocalEntityManagerFactoryBean.java
  3. 1
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/Car.java
  4. 1
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/Employee.java
  5. 2
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeCategory.java
  6. 3
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeCategoryConverter.java
  7. 2
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeKind.java
  8. 3
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeKindConverter.java
  9. 1
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeLocation.java
  10. 1
      spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeLocationConverter.java
  11. 30
      spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryScanIntegrationTests.java
  12. 30
      spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryScanIntegrationTests.java
  13. 3
      spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java
  14. 14
      spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesScannerTests.java
  15. 28
      spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager-scan.xml
  16. 4
      spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml
  17. 36
      spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-scan.xml

3
spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java

@ -75,14 +75,11 @@ import org.springframework.util.ClassUtils; @@ -75,14 +75,11 @@ import org.springframework.util.ClassUtils;
* @author Juergen Hoeller
* @author Rod Johnson
* @since 2.0
* @see #setPersistenceXmlLocation
* @see #setJpaProperties
* @see #setJpaVendorAdapter
* @see #setLoadTimeWeaver
* @see #setDataSource
* @see EntityManagerFactoryInfo
* @see LocalEntityManagerFactoryBean
* @see org.springframework.orm.jpa.support.SharedEntityManagerBean
* @see jakarta.persistence.spi.PersistenceProvider#createContainerEntityManagerFactory
*/
@SuppressWarnings("serial")

12
spring-orm/src/main/java/org/springframework/orm/jpa/LocalEntityManagerFactoryBean.java

@ -51,10 +51,8 @@ import org.springframework.lang.Nullable; @@ -51,10 +51,8 @@ import org.springframework.lang.Nullable;
* @since 2.0
* @see #setJpaProperties
* @see #setJpaVendorAdapter
* @see JpaTransactionManager#setEntityManagerFactory
* @see #setDataSource
* @see LocalContainerEntityManagerFactoryBean
* @see org.springframework.jndi.JndiObjectFactoryBean
* @see org.springframework.orm.jpa.support.SharedEntityManagerBean
* @see jakarta.persistence.Persistence#createEntityManagerFactory
* @see jakarta.persistence.spi.PersistenceProvider#createEntityManagerFactory
*/
@ -63,6 +61,8 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB @@ -63,6 +61,8 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
private static final String DATASOURCE_PROPERTY = "jakarta.persistence.dataSource";
private static final String NON_JTA_DATASOURCE_PROPERTY = "jakarta.persistence.nonJtaDataSource";
/**
* Specify the JDBC DataSource that the JPA persistence provider is supposed
@ -78,9 +78,11 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB @@ -78,9 +78,11 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
public void setDataSource(@Nullable DataSource dataSource) {
if (dataSource != null) {
getJpaPropertyMap().put(DATASOURCE_PROPERTY, dataSource);
getJpaPropertyMap().put(NON_JTA_DATASOURCE_PROPERTY, dataSource);
}
else {
getJpaPropertyMap().remove(DATASOURCE_PROPERTY);
getJpaPropertyMap().remove(NON_JTA_DATASOURCE_PROPERTY);
}
}
@ -111,8 +113,8 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB @@ -111,8 +113,8 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
// Create EntityManagerFactory directly through PersistenceProvider.
EntityManagerFactory emf = provider.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap());
if (emf == null) {
throw new IllegalStateException(
"PersistenceProvider [" + provider + "] did not return an EntityManagerFactory for name '" +
throw new PersistenceException(
"PersistenceProvider [" + provider + "] could not find persistence unit for name '" +
getPersistenceUnitName() + "'");
}
return emf;

1
spring-orm/src/test/java/org/springframework/orm/jpa/domain/Car.java

@ -47,4 +47,5 @@ public class Car { @@ -47,4 +47,5 @@ public class Car {
String getModel() {
return model;
}
}

1
spring-orm/src/test/java/org/springframework/orm/jpa/domain/Employee.java

@ -86,4 +86,5 @@ public class Employee { @@ -86,4 +86,5 @@ public class Employee {
@PreRemove
public void preRemove() {
}
}

2
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeCategory.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.orm.jpa.domain;
public class EmployeeCategory {
private String name;
public String getName() {
@ -26,4 +27,5 @@ public class EmployeeCategory { @@ -26,4 +27,5 @@ public class EmployeeCategory {
public void setName(String name) {
this.name = name;
}
}

3
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeCategoryConverter.java

@ -17,7 +17,9 @@ @@ -17,7 +17,9 @@
package org.springframework.orm.jpa.domain;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter
public class EmployeeCategoryConverter implements AttributeConverter<EmployeeCategory, String> {
@Override
@ -37,4 +39,5 @@ public class EmployeeCategoryConverter implements AttributeConverter<EmployeeCat @@ -37,4 +39,5 @@ public class EmployeeCategoryConverter implements AttributeConverter<EmployeeCat
}
return null;
}
}

2
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeKind.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.orm.jpa.domain;
public class EmployeeKind {
private String name;
public String getName() {
@ -26,4 +27,5 @@ public class EmployeeKind { @@ -26,4 +27,5 @@ public class EmployeeKind {
public void setName(String name) {
this.name = name;
}
}

3
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeKindConverter.java

@ -17,7 +17,9 @@ @@ -17,7 +17,9 @@
package org.springframework.orm.jpa.domain;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter(autoApply = true)
public class EmployeeKindConverter implements AttributeConverter<EmployeeKind, String> {
@Override
@ -37,4 +39,5 @@ public class EmployeeKindConverter implements AttributeConverter<EmployeeKind, S @@ -37,4 +39,5 @@ public class EmployeeKindConverter implements AttributeConverter<EmployeeKind, S
}
return null;
}
}

1
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeLocation.java

@ -27,4 +27,5 @@ public class EmployeeLocation { @@ -27,4 +27,5 @@ public class EmployeeLocation {
public void setLocation(String location) {
this.location = location;
}
}

1
spring-orm/src/test/java/org/springframework/orm/jpa/domain/EmployeeLocationConverter.java

@ -39,4 +39,5 @@ public class EmployeeLocationConverter implements AttributeConverter<EmployeeLoc @@ -39,4 +39,5 @@ public class EmployeeLocationConverter implements AttributeConverter<EmployeeLoc
}
return null;
}
}

30
spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryScanIntegrationTests.java

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.jpa.eclipselink;
/**
* @author Juergen Hoeller
*/
class EclipseLinkEntityManagerFactoryScanIntegrationTests extends EclipseLinkEntityManagerFactoryIntegrationTests {
@Override
protected String[] getConfigLocations() {
return new String[] {"/org/springframework/orm/jpa/eclipselink/eclipselink-manager-scan.xml",
"/org/springframework/orm/jpa/memdb.xml", "/org/springframework/orm/jpa/inject.xml"};
}
}

30
spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryScanIntegrationTests.java

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.jpa.hibernate;
/**
* @author Juergen Hoeller
*/
class HibernateEntityManagerFactoryScanIntegrationTests extends HibernateEntityManagerFactoryIntegrationTests {
@Override
protected String[] getConfigLocations() {
return new String[] {"/org/springframework/orm/jpa/hibernate/hibernate-manager-scan.xml",
"/org/springframework/orm/jpa/memdb.xml", "/org/springframework/orm/jpa/inject.xml"};
}
}

3
spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java

@ -71,7 +71,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests { @@ -71,7 +71,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
PersistenceManagedTypes persistenceManagedTypes = freshApplicationContext.getBean(
"persistenceManagedTypes", PersistenceManagedTypes.class);
assertThat(persistenceManagedTypes.getManagedClassNames()).containsExactlyInAnyOrder(
DriversLicense.class.getName(), Person.class.getName(), Employee.class.getName(),
Person.class.getName(), DriversLicense.class.getName(), Employee.class.getName(),
EmployeeCategoryConverter.class.getName(), EmployeeKindConverter.class.getName(),
EmployeeLocationConverter.class.getName(), Car.class.getName());
assertThat(persistenceManagedTypes.getManagedPackages()).isEmpty();
assertThat(freshApplicationContext.getBean(

14
spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesScannerTests.java

@ -26,6 +26,8 @@ import org.springframework.core.io.DefaultResourceLoader; @@ -26,6 +26,8 @@ import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.orm.jpa.domain.Car;
import org.springframework.orm.jpa.domain.DriversLicense;
import org.springframework.orm.jpa.domain.Employee;
import org.springframework.orm.jpa.domain.EmployeeCategoryConverter;
import org.springframework.orm.jpa.domain.EmployeeKindConverter;
import org.springframework.orm.jpa.domain.EmployeeLocationConverter;
import org.springframework.orm.jpa.domain.Person;
import org.springframework.orm.jpa.domain2.entity.User;
@ -44,15 +46,17 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -44,15 +46,17 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
*/
class PersistenceManagedTypesScannerTests {
public static final DefaultResourceLoader RESOURCE_LOADER = new DefaultResourceLoader();
private final DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
private final PersistenceManagedTypesScanner scanner = new PersistenceManagedTypesScanner(resourceLoader);
private final PersistenceManagedTypesScanner scanner = new PersistenceManagedTypesScanner(RESOURCE_LOADER);
@Test
void scanPackageWithOnlyEntities() {
PersistenceManagedTypes managedTypes = this.scanner.scan("org.springframework.orm.jpa.domain");
assertThat(managedTypes.getManagedClassNames()).containsExactlyInAnyOrder(
Person.class.getName(), DriversLicense.class.getName(), Employee.class.getName(),
EmployeeCategoryConverter.class.getName(), EmployeeKindConverter.class.getName(),
EmployeeLocationConverter.class.getName(), Car.class.getName());
assertThat(managedTypes.getManagedPackages()).isEmpty();
}
@ -61,11 +65,13 @@ class PersistenceManagedTypesScannerTests { @@ -61,11 +65,13 @@ class PersistenceManagedTypesScannerTests {
void scanPackageInvokesManagedClassNamesFilter() {
ManagedClassNameFilter filter = mock(ManagedClassNameFilter.class);
given(filter.matches(anyString())).willReturn(true);
new PersistenceManagedTypesScanner(RESOURCE_LOADER, filter)
new PersistenceManagedTypesScanner(resourceLoader, filter)
.scan("org.springframework.orm.jpa.domain");
verify(filter).matches(Person.class.getName());
verify(filter).matches(DriversLicense.class.getName());
verify(filter).matches(Employee.class.getName());
verify(filter).matches(EmployeeCategoryConverter.class.getName());
verify(filter).matches(EmployeeKindConverter.class.getName());
verify(filter).matches(EmployeeLocationConverter.class.getName());
verify(filter).matches(Car.class.getName());
verifyNoMoreInteractions(filter);
@ -75,7 +81,7 @@ class PersistenceManagedTypesScannerTests { @@ -75,7 +81,7 @@ class PersistenceManagedTypesScannerTests {
void scanPackageWithUseManagedClassNamesFilter() {
List<String> candidates = List.of(Person.class.getName(), DriversLicense.class.getName());
PersistenceManagedTypes managedTypes = new PersistenceManagedTypesScanner(
RESOURCE_LOADER, candidates::contains).scan("org.springframework.orm.jpa.domain");
resourceLoader, candidates::contains).scan("org.springframework.orm.jpa.domain");
assertThat(managedTypes.getManagedClassNames()).containsExactlyInAnyOrder(
Person.class.getName(), DriversLicense.class.getName());
assertThat(managedTypes.getManagedPackages()).isEmpty();

28
spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager-scan.xml

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Person"/>
<property name="packagesToScan" value="org.springframework.orm.jpa.domain*"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="HSQL"/>
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="eclipselink.weaving">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</beans>

4
spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml

@ -5,10 +5,6 @@ @@ -5,10 +5,6 @@
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="org/springframework/orm/jpa/domain/persistence.xml"/>
<!--
<property name="persistenceUnitName" value="Person"/>
<property name="packagesToScan" value="org.springframework.orm.jpa.domain"/>
-->
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">

36
spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-scan.xml

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" primary="true">
<property name="persistenceUnitName" value="Person"/>
<property name="packagesToScan" value="org.springframework.orm.jpa.domain*"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL"/>
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="hibernate.current_session_context_class">org.springframework.orm.jpa.hibernate.SpringSessionContext</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
</props>
</property>
<property name="bootstrapExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="hibernateStatistics" factory-bean="entityManagerFactory" factory-method="getStatistics" lazy-init="true"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>
Loading…
Cancel
Save