From 620e83c35d52a4da3453f091c8c47a9d01a8e3dd Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 5 Jul 2018 16:48:35 +0200 Subject: [PATCH] SpringBeanContainer is public for custom JPA configuration purposes Issue: SPR-16305 --- .../hibernate5/LocalSessionFactoryBean.java | 10 +++++ .../LocalSessionFactoryBuilder.java | 21 ++++++++-- .../orm/hibernate5/SpringBeanContainer.java | 42 ++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java index e1d0164eca..b9518299bc 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java @@ -57,12 +57,21 @@ import org.springframework.util.ClassUtils; * SessionFactory can then be passed to data access objects via dependency injection. * *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3, as of Spring 5.1. + * Set up with Hibernate 5.3, {@code LocalSessionFactoryBean} is an immediate alternative + * to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for common + * JPA purposes: In particular with Hibernate 5.3, the Hibernate {@code SessionFactory} + * will natively expose the JPA {@code EntityManagerFactory} interface as well, and + * Hibernate {@code BeanContainer} integration will be registered out of the box. + * In combination with {@link HibernateTransactionManager}, this naturally allows for + * mixing JPA access code with native Hibernate access code within the same transaction. * * @author Juergen Hoeller * @since 4.2 * @see #setDataSource * @see #setPackagesToScan + * @see HibernateTransactionManager * @see LocalSessionFactoryBuilder + * @see org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean */ public class LocalSessionFactoryBean extends HibernateExceptionTranslator implements FactoryBean, ResourceLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean { @@ -446,6 +455,7 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator * it if possible. This requires a Spring {@link ConfigurableListableBeanFactory} * and Hibernate 5.3 or higher on the classpath. * @since 5.1 + * @see SpringBeanContainer * @see LocalSessionFactoryBuilder#setBeanContainer */ @Override diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java index 4d8062fbb2..594a8b9fca 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java @@ -67,16 +67,30 @@ import org.springframework.util.ClassUtils; /** * A Spring-provided extension of the standard Hibernate {@link Configuration} class, * adding {@link SpringSessionContext} as a default and providing convenient ways - * to specify a DataSource and an application class loader. + * to specify a JDBC {@link DataSource} and an application class loader. * - *

This is designed for programmatic use, e.g. in {@code @Bean} factory methods. - * Consider using {@link LocalSessionFactoryBean} for XML bean definition files. + *

This is designed for programmatic use, e.g. in {@code @Bean} factory methods; + * consider using {@link LocalSessionFactoryBean} for XML bean definition files. + * Typically combined with {@link HibernateTransactionManager} for declarative + * transactions against the {@code SessionFactory} and its JDBC {@code DataSource}. * *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3, as of Spring 5.1. + * Set up with Hibernate 5.2/5.3, this builder is also a convenient way to set up + * a JPA {@code EntityManagerFactory} since the Hibernate {@code SessionFactory} + * natively exposes the JPA {@code EntityManagerFactory} interface as well now. + * + *

This builder supports Hibernate 5.3 {@code BeanContainer} integration, + * {@link MetadataSources} from custom {@link BootstrapServiceRegistryBuilder} + * setup, as well as other advanced Hibernate configuration options beyond the + * standard JPA bootstrap contract. * * @author Juergen Hoeller * @since 4.2 + * @see HibernateTransactionManager * @see LocalSessionFactoryBean + * @see #setBeanContainer + * @see #LocalSessionFactoryBuilder(DataSource, ResourceLoader, MetadataSources) + * @see BootstrapServiceRegistryBuilder */ @SuppressWarnings("serial") public class LocalSessionFactoryBuilder extends Configuration { @@ -235,6 +249,7 @@ public class LocalSessionFactoryBuilder extends Configuration { *

Note: Bean container integration requires Hibernate 5.3 or higher. * It enables autowiring of Hibernate attribute converters and entity listeners. * @since 5.1 + * @see SpringBeanContainer * @see AvailableSettings#BEAN_CONTAINER */ public LocalSessionFactoryBuilder setBeanContainer(ConfigurableListableBeanFactory beanFactory) { diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java index 499d3dab77..258c8d4f87 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java @@ -26,23 +26,63 @@ import org.hibernate.resource.beans.spi.BeanInstanceProducer; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; /** * Spring's implementation of Hibernate 5.3's {@link BeanContainer} SPI, * delegating to a Spring {@link ConfigurableListableBeanFactory}. * + *

Auto-configured by {@link LocalSessionFactoryBean#setBeanFactory}, + * programmatically supported via {@link LocalSessionFactoryBuilder#setBeanContainer}, + * and manually configurable through a "hibernate.resource.beans.container" entry + * in JPA properties, e.g.: + * + *

+ * <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+ *   ...
+ *   <property name="jpaPropertyMap">
+ * 	   <map>
+ *       <entry key="hibernate.resource.beans.container">
+ * 	       <bean class="org.springframework.orm.hibernate5.SpringBeanContainer"/>
+ * 	     </entry>
+ * 	   </map>
+ *   </property>
+ * </bean>
+ * + * Or in Java-based JPA configuration: + * + *
+ * LocalContainerEntityManagerFactoryBean emfb = ...
+ * emfb.getJpaPropertyMap().put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
+ * 
+ * + * Please note that Spring's {@link LocalSessionFactoryBean} is an immediate alternative + * to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for common + * JPA purposes: In particular with Hibernate 5.3, the Hibernate {@code SessionFactory} + * will natively expose the JPA {@code EntityManagerFactory} interface as well, and + * Hibernate {@code BeanContainer} integration will be registered out of the box. + * * @author Juergen Hoeller * @since 5.1 + * @see LocalSessionFactoryBean#setBeanFactory + * @see LocalSessionFactoryBuilder#setBeanContainer + * @see org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#setJpaPropertyMap + * @see org.hibernate.cfg.AvailableSettings#BEAN_CONTAINER */ -final class SpringBeanContainer implements BeanContainer { +public final class SpringBeanContainer implements BeanContainer { private final ConfigurableListableBeanFactory beanFactory; private final Map> beanCache = new ConcurrentReferenceHashMap<>(); + /** + * Instantiate a new SpringBeanContainer for the given bean factory. + * @param beanFactory the Spring bean factory to delegate to + */ public SpringBeanContainer(ConfigurableListableBeanFactory beanFactory) { + Assert.notNull(beanFactory, "ConfigurableListableBeanFactory is required"); this.beanFactory = beanFactory; }