mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
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
This commit is contained in:
-3
@@ -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")
|
||||
|
||||
+7
-5
@@ -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
|
||||
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
|
||||
@@ -47,4 +47,5 @@ public class Car {
|
||||
String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,4 +86,5 @@ public class Employee {
|
||||
@PreRemove
|
||||
public void preRemove() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
@@ -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
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,4 +27,5 @@ public class EmployeeLocation {
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -39,4 +39,5 @@ public class EmployeeLocationConverter implements AttributeConverter<EmployeeLoc
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+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
@@ -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"};
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -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(
|
||||
|
||||
+10
-4
@@ -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;
|
||||
*/
|
||||
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 {
|
||||
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 {
|
||||
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
@@ -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
@@ -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
@@ -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>
|
||||
Reference in New Issue
Block a user