Adapt EntityManagerFactoryBuilder to work with multiple data sources

This commit allows EntityManagerFactoryBuilder to provide the JPA
properties to use according to the DataSource used to build the
EntityManagerFactory. Previously the JPA properties were computed only
once based on the primary data source, which was a problem since its
default DDL setting may be different.

EntityManagerFactoryBuilder takes a function that provides the JPA
properties based on a data source, rather than the properties
themselves. Constructors with the previous variant have been deprecated
as a result.

Closes gh-44516
This commit is contained in:
Stéphane Nicoll
2025-03-06 11:22:03 +01:00
parent d097870de5
commit e06244d007
10 changed files with 362 additions and 47 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@@ -16,6 +16,10 @@
package org.springframework.boot.docs.howto.dataaccess.usemultipleentitymanagers;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -48,7 +52,9 @@ public class MyAdditionalEntityManagerFactoryConfiguration {
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);
Function<DataSource, Map<String, ?>> jpaPropertiesFactory = (dataSource) -> createJpaProperties(dataSource,
jpaProperties.getProperties());
return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaPropertiesFactory, null);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
@@ -56,4 +62,10 @@ public class MyAdditionalEntityManagerFactoryConfiguration {
return new HibernateJpaVendorAdapter();
}
private Map<String, ?> createJpaProperties(DataSource dataSource, Map<String, ?> existingProperties) {
Map<String, ?> jpaProperties = new LinkedHashMap<>(existingProperties);
// ... map JPA properties that require the DataSource (e.g. DDL flags)
return jpaProperties;
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.boot.docs.howto.dataaccess.usemultipleentitymanagers
import javax.sql.DataSource
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.context.properties.ConfigurationProperties
@@ -27,6 +25,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.orm.jpa.JpaVendorAdapter
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
import javax.sql.DataSource
@Suppress("UNUSED_PARAMETER")
@Configuration(proxyBeanMethods = false)
@@ -51,7 +50,9 @@ class MyAdditionalEntityManagerFactoryConfiguration {
private fun createEntityManagerFactoryBuilder(jpaProperties: JpaProperties): EntityManagerFactoryBuilder {
val jpaVendorAdapter = createJpaVendorAdapter(jpaProperties)
return EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.properties, null)
val jpaPropertiesFactory = { dataSource: DataSource ->
createJpaProperties(dataSource, jpaProperties.properties) }
return EntityManagerFactoryBuilder(jpaVendorAdapter, jpaPropertiesFactory, null)
}
private fun createJpaVendorAdapter(jpaProperties: JpaProperties): JpaVendorAdapter {
@@ -59,4 +60,10 @@ class MyAdditionalEntityManagerFactoryConfiguration {
return HibernateJpaVendorAdapter()
}
private fun createJpaProperties(dataSource: DataSource, existingProperties: Map<String, *>): Map<String, *> {
val jpaProperties: Map<String, *> = LinkedHashMap(existingProperties)
// ... map JPA properties that require the DataSource (e.g. DDL flags)
return jpaProperties
}
}