Skip to content

Commit 6bbd36c

Browse files
committed
Merge branch '2.3.x' into 2.4.x
Closes gh-26159
2 parents 54613c7 + 57c199d commit 6bbd36c

File tree

3 files changed

+84
-36
lines changed

3 files changed

+84
-36
lines changed

spring-boot-project/spring-boot-docs/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ dependencies {
8080
implementation("org.assertj:assertj-core")
8181
implementation("org.glassfish.jersey.core:jersey-server")
8282
implementation("org.hibernate:hibernate-jcache")
83+
implementation("org.springframework:spring-orm")
8384
implementation("org.springframework:spring-test")
8485
implementation("org.springframework:spring-web")
8586
implementation("org.springframework:spring-webflux")

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

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,62 +1853,44 @@ Spring Boot auto-configuration switches off its entity manager in the presence o
18531853

18541854

18551855
[[howto-use-two-entity-managers]]
1856-
=== Use Two EntityManagers
1857-
Even if the default `EntityManagerFactory` works fine, you need to define a new one, otherwise the presence of the second bean of that type switches off the default.
1858-
You can use the `EntityManagerBuilder` provided by Spring Boot to help you to create one.
1859-
Alternatively, you can use the `LocalContainerEntityManagerFactoryBean` directly from Spring ORM, as shown in the following example:
1856+
[[howto-use-multiple-entity-managers]]
1857+
=== Using Multiple EntityManagerFactories
1858+
If you need to use JPA against multiple data sources, you likely need one `EntityManagerFactory` per data source.
1859+
The `LocalContainerEntityManagerFactoryBean` from Spring ORM allows you to configure an `EntityManagerFactory` for your needs.
1860+
You can also reuse `JpaProperties` to bind settings for each `EntityManagerFactory`, as shown in the following example:
18601861

18611862
[source,java,indent=0,subs="verbatim,quotes,attributes"]
18621863
----
1863-
// add two data sources configured as above
1864-
1865-
@Bean
1866-
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
1867-
EntityManagerFactoryBuilder builder) {
1868-
return builder
1869-
.dataSource(customerDataSource())
1870-
.packages(Customer.class)
1871-
.persistenceUnit("customers")
1872-
.build();
1873-
}
1874-
1875-
@Bean
1876-
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
1877-
EntityManagerFactoryBuilder builder) {
1878-
return builder
1879-
.dataSource(orderDataSource())
1880-
.packages(Order.class)
1881-
.persistenceUnit("orders")
1882-
.build();
1883-
}
1864+
include::{code-examples}/jpa/CustomEntityManagerFactoryExample.java[tag=configuration]
18841865
----
18851866

1867+
The example above creates an `EntityManagerFactory` using a `DataSource` bean named `firstDataSource`.
1868+
It scans entities located in the same package as `Order`.
1869+
It is possible to map additional JPA properties using the `app.first.jpa` namespace.
1870+
18861871
NOTE: When you create a bean for `LocalContainerEntityManagerFactoryBean` yourself, any customization that was applied during the creation of the auto-configured `LocalContainerEntityManagerFactoryBean` is lost.
18871872
For example, in case of Hibernate, any properties under the `spring.jpa.hibernate` prefix will not be automatically applied to your `LocalContainerEntityManagerFactoryBean`.
18881873
If you were relying on these properties for configuring things like the naming strategy or the DDL mode, you will need to explicitly configure that when creating the `LocalContainerEntityManagerFactoryBean` bean.
1889-
On the other hand, properties that get applied to the auto-configured `EntityManagerFactoryBuilder`, which are specified via `spring.jpa.properties`, will automatically be applied, provided you use the auto-configured `EntityManagerFactoryBuilder` to build the `LocalContainerEntityManagerFactoryBean` bean.
18901874

1891-
The configuration above almost works on its own.
1892-
To complete the picture, you need to configure `TransactionManagers` for the two `EntityManagers` as well.
1893-
If you mark one of them as `@Primary`, it could be picked up by the default `JpaTransactionManager` in Spring Boot.
1894-
The other would have to be explicitly injected into a new instance.
1875+
You should provide a similar configuration for any additional data sources for which you need JPA access.
1876+
To complete the picture, you need to configure a `JpaTransactionManager` for each `EntityManagerFactory` as well.
18951877
Alternatively, you might be able to use a JTA transaction manager that spans both.
18961878

18971879
If you use Spring Data, you need to configure `@EnableJpaRepositories` accordingly, as shown in the following example:
18981880

18991881
[source,java,indent=0,subs="verbatim,quotes,attributes"]
19001882
----
19011883
@Configuration(proxyBeanMethods = false)
1902-
@EnableJpaRepositories(basePackageClasses = Customer.class,
1903-
entityManagerFactoryRef = "customerEntityManagerFactory")
1904-
public class CustomerConfiguration {
1884+
@EnableJpaRepositories(basePackageClasses = Order.class,
1885+
entityManagerFactoryRef = "firstEntityManagerFactory")
1886+
public class OrderConfiguration {
19051887
...
19061888
}
19071889
19081890
@Configuration(proxyBeanMethods = false)
1909-
@EnableJpaRepositories(basePackageClasses = Order.class,
1910-
entityManagerFactoryRef = "orderEntityManagerFactory")
1911-
public class OrderConfiguration {
1891+
@EnableJpaRepositories(basePackageClasses = Customer.class,
1892+
entityManagerFactoryRef = "secondEntityManagerFactory")
1893+
public class CustomerConfiguration {
19121894
...
19131895
}
19141896
----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2012-2021 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+
* https://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.docs.jpa;
18+
19+
import javax.sql.DataSource;
20+
21+
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
22+
import org.springframework.boot.context.properties.ConfigurationProperties;
23+
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.orm.jpa.JpaVendorAdapter;
26+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
27+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
28+
29+
/**
30+
* Example configuration for a custom JPA entity manager.
31+
*
32+
* @author Stephane Nicoll
33+
*/
34+
public class CustomEntityManagerFactoryExample {
35+
36+
// tag::configuration[]
37+
@Bean
38+
@ConfigurationProperties("app.jpa.first")
39+
public JpaProperties firstJpaProperties() {
40+
return new JpaProperties();
41+
}
42+
43+
@Bean
44+
public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource firstDataSource,
45+
JpaProperties firstJpaProperties) {
46+
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(firstJpaProperties);
47+
return builder.dataSource(firstDataSource).packages(Order.class).persistenceUnit("firstDs").build();
48+
}
49+
50+
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
51+
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
52+
return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);
53+
}
54+
55+
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
56+
// Map JPA properties as needed
57+
return new HibernateJpaVendorAdapter();
58+
}
59+
// end::configuration[]
60+
61+
private static class Order {
62+
63+
}
64+
65+
}

0 commit comments

Comments
 (0)