Skip to content

Commit 068040e

Browse files
committed
Register SpringBeanContainer with default Hibernate setup
Closes gh-13717
1 parent 7bf3229 commit 068040e

File tree

6 files changed

+106
-10
lines changed

6 files changed

+106
-10
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
package org.springframework.boot.autoconfigure.orm.jpa;
1818

19+
import java.util.ArrayList;
1920
import java.util.Arrays;
2021
import java.util.Collection;
2122
import java.util.LinkedHashMap;
22-
import java.util.LinkedList;
2323
import java.util.List;
2424
import java.util.Map;
2525
import java.util.function.Supplier;
@@ -31,8 +31,10 @@
3131
import org.apache.commons.logging.LogFactory;
3232
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
3333
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
34+
import org.hibernate.cfg.AvailableSettings;
3435

3536
import org.springframework.beans.factory.ObjectProvider;
37+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3638
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
3739
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
3840
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -43,6 +45,7 @@
4345
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
4446
import org.springframework.context.annotation.Configuration;
4547
import org.springframework.jndi.JndiLocatorDelegate;
48+
import org.springframework.orm.hibernate5.SpringBeanContainer;
4649
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
4750
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
4851
import org.springframework.transaction.jta.JtaTransactionManager;
@@ -85,6 +88,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
8588
private final List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers;
8689

8790
HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
91+
ConfigurableListableBeanFactory beanFactory,
8892
ObjectProvider<JtaTransactionManager> jtaTransactionManager,
8993
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
9094
HibernateProperties hibernateProperties,
@@ -101,22 +105,25 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
101105
metadataProviders.getIfAvailable());
102106
this.hibernatePropertiesCustomizers = determineHibernatePropertiesCustomizers(
103107
physicalNamingStrategy.getIfAvailable(),
104-
implicitNamingStrategy.getIfAvailable(), hibernatePropertiesCustomizers
105-
.orderedStream().collect(Collectors.toList()));
108+
implicitNamingStrategy.getIfAvailable(), beanFactory,
109+
hibernatePropertiesCustomizers.orderedStream()
110+
.collect(Collectors.toList()));
106111
}
107112

108113
private List<HibernatePropertiesCustomizer> determineHibernatePropertiesCustomizers(
109114
PhysicalNamingStrategy physicalNamingStrategy,
110115
ImplicitNamingStrategy implicitNamingStrategy,
116+
ConfigurableListableBeanFactory beanFactory,
111117
List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
118+
List<HibernatePropertiesCustomizer> customizers = new ArrayList<>();
119+
customizers.add((properties) -> properties.put(AvailableSettings.BEAN_CONTAINER,
120+
new SpringBeanContainer(beanFactory)));
112121
if (physicalNamingStrategy != null || implicitNamingStrategy != null) {
113-
LinkedList<HibernatePropertiesCustomizer> customizers = new LinkedList<>(
114-
hibernatePropertiesCustomizers);
115-
customizers.addFirst(new NamingStrategiesHibernatePropertiesCustomizer(
122+
customizers.add(new NamingStrategiesHibernatePropertiesCustomizer(
116123
physicalNamingStrategy, implicitNamingStrategy));
117-
return customizers;
118124
}
119-
return hibernatePropertiesCustomizers;
125+
customizers.addAll(hibernatePropertiesCustomizers);
126+
return customizers;
120127
}
121128

122129
@Override

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.zaxxer.hikari.HikariDataSource;
3636
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
3737
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
38+
import org.hibernate.cfg.AvailableSettings;
3839
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
3940
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
4041
import org.hibernate.internal.SessionFactoryImpl;
@@ -361,6 +362,27 @@ public void hibernatePropertiesCustomizerTakesPrecedenceOverStrategyInstancesAnd
361362
});
362363
}
363364

365+
@Test
366+
public void eventListenerCanBeRegisteredAsBeans() {
367+
contextRunner().withUserConfiguration(TestInitializedJpaConfiguration.class)
368+
.withClassLoader(new HideDataScriptClassLoader())
369+
.withPropertyValues("spring.jpa.show-sql=true",
370+
"spring.jpa.hibernate.ddl-auto:create-drop",
371+
"spring.datasource.data:classpath:/city.sql")
372+
.run((context) -> {
373+
// See CityListener
374+
assertThat(context).hasSingleBean(City.class);
375+
assertThat(context.getBean(City.class).getName())
376+
.isEqualTo("Washington");
377+
});
378+
}
379+
380+
@Test
381+
public void hibernatePropertiesCustomizerCanDisableBeanContainer() {
382+
contextRunner().withUserConfiguration(DisableBeanContainerConfiguration.class)
383+
.run((context) -> assertThat(context).doesNotHaveBean(City.class));
384+
}
385+
364386
@Configuration
365387
@TestAutoConfigurationPackage(City.class)
366388
static class TestInitializedJpaConfiguration {
@@ -420,6 +442,17 @@ public HibernatePropertiesCustomizer testHibernatePropertiesCustomizer() {
420442

421443
}
422444

445+
@Configuration
446+
static class DisableBeanContainerConfiguration {
447+
448+
@Bean
449+
public HibernatePropertiesCustomizer disableBeanContainerHibernatePropertiesCustomizer() {
450+
return (hibernateProperties) -> hibernateProperties
451+
.remove(AvailableSettings.BEAN_CONTAINER);
452+
}
453+
454+
}
455+
423456
public static class TestJtaPlatform implements JtaPlatform {
424457

425458
@Override

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/test/City.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,10 +20,12 @@
2020

2121
import javax.persistence.Column;
2222
import javax.persistence.Entity;
23+
import javax.persistence.EntityListeners;
2324
import javax.persistence.GeneratedValue;
2425
import javax.persistence.Id;
2526

2627
@Entity
28+
@EntityListeners(CityListener.class)
2729
public class City implements Serializable {
2830

2931
private static final long serialVersionUID = 1L;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.orm.jpa.test;
18+
19+
import javax.persistence.PostLoad;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
23+
24+
public class CityListener {
25+
26+
private ConfigurableBeanFactory beanFactory;
27+
28+
public CityListener() {
29+
}
30+
31+
@Autowired
32+
public CityListener(ConfigurableBeanFactory beanFactory) {
33+
this.beanFactory = beanFactory;
34+
}
35+
36+
@PostLoad
37+
public void postLoad(City city) {
38+
if (this.beanFactory != null) {
39+
this.beanFactory.registerSingleton(City.class.getName(), city);
40+
}
41+
}
42+
43+
}

spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,17 @@ for more details.
20002000

20012001

20022002

2003+
[[howto-use-dependency-injection-hibernate-components]]
2004+
=== Use Dependency Injection in Hibernate Components
2005+
By default, Spring Boot registers a `BeanContainer` implementation that uses the
2006+
`BeanFactory` so that converters and entity listeners can use regular dependency
2007+
injection.
2008+
2009+
You can disable or tune this behaviour by registering a `HibernatePropertiesCustomizer`
2010+
that remove or change the `hibernate.resource.beans.container` property.
2011+
2012+
2013+
20032014
[[howto-use-custom-entity-manager]]
20042015
=== Use a Custom EntityManagerFactory
20052016
To take full control of the configuration of the `EntityManagerFactory`, you need to add

spring-boot-project/spring-boot-docs/src/main/asciidoc/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
6666
:code-examples: ../java/org/springframework/boot/docs
6767
:test-examples: ../../test/java/org/springframework/boot/docs
6868
:gradle-user-guide: https://docs.gradle.org/4.2.1/userguide
69-
:hibernate-documentation: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html
69+
:hibernate-documentation: https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html
7070
:jetty-documentation: https://www.eclipse.org/jetty/documentation/9.4.x
7171
:jooq-manual: https://www.jooq.org/doc/{jooq-version}/manual-single-page
7272
:micrometer-concepts-documentation: https://micrometer.io/docs/concepts

0 commit comments

Comments
 (0)