How to commit changes? - spring

In my Spring Boot application the SQLite file (myapp.db) will be used in an Android app, pre-populated. My problem occurs when I try to copy this SQLite file. When a connection is opened it creates temporary files:
myapp.db
myapp.db-wal
myapp.db-shm
These files contain pending changes, so when I copy myapp.db, the tables are empty. I tried to close the connection and stopping the server but changes never are committed to myapp.db.
Configuration class:
#Configuration
#EnableJpaRepositories(
transactionManagerRef = "sqliteTransactionManager",
entityManagerFactoryRef = "sqliteEntityManagerFactory",
basePackages = {
"com.app.sqlite.domain",
"com.app.sqlite.repository" }
)
public class DatabaseConfiguration {
private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
#Bean(name = "sqlite_db")
public DataSource sqliteDataSource() {
HikariConfig config = new HikariConfig();
config.setPoolName("sqlite_db");
config.setAutoCommit(false);
config.setJdbcUrl("jdbc:sqlite:/dbgen/myapp.db");
config.setDriverClassName("org.sqlite.JDBC");
DataSource dataSource = new HikariDataSource(config);
return dataSource;
}
#Bean(name = "sqliteEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "com.app.config.SQLiteDialect");
LocalContainerEntityManagerFactoryBean emf = builder.dataSource(sqliteDataSource())
.packages(WorkoutSQLITE.class).persistenceUnit("sqliteunit").build();
emf.setJpaProperties(properties);
return emf;
}
#Bean(name = "sqliteTransactionManager")
public JpaTransactionManager dbTransactionManager(
#Qualifier("sqliteEntityManagerFactory") final EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
How can I commit/synchronize changes to myapp.db?

Related

SpringBoot multiple datasources Junit test fails with H2

I have a springboot project which requests data from 2 datasources (2 MariaDB SQL databases) and I have successfully implemented it by creating 2 configuration classes for each DB and their respective Beans. My DB used by default is the User DB (#Primary annotation used in its config class).
I want to test my user repository layer by using an H2 database and for that, I have created a configuration class for this datasource and declared the datasource properties in my application-test.properties file.
The problem is when I run my tests, I have a BeanDefinitionOverrideException saying that there's a collision of my bean names for my 1th DB and H2 DB (a bean with this name already exist...) since they use the same JPA repository package.
How can I use H2 database for my tests and tell Spring to not load the beans for my 2 MariaDB datasources ?
**Configuration of the 1th DB :
**
#Configuration
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager"
)
public class PersistenceUserConfiguration {
#Autowired
private Environment env;
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean userEntityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan(
new String[] { "com.baeldung.multipledb.model.user" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
public DataSource userDataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("user.jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Primary
#Bean
public PlatformTransactionManager userTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
userEntityManager().getObject());
return transactionManager;
}
}
**Configuration of the 2nd DB :
**
#Configuration
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.product",
entityManagerFactoryRef = "productEntityManager",
transactionManagerRef = "productTransactionManager"
)
public class PersistenceProductConfiguration {
#Autowired
private Environment env;
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean productEntityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(productDataSource());
em.setPackagesToScan(
new String[] { "com.baeldung.multipledb.model.product" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
public DataSource productDataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("product.jdbc.url"));
dataSource.setproductname(env.getProperty("jdbc.product"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Primary
#Bean
public PlatformTransactionManager productTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
productEntityManager().getObject());
return transactionManager;
}
}
}
**Configuration of H2 DB for tests :
**
#Profile("test")
#Configuration
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.user",
entityManagerFactoryRef = "h2EntityManager",
transactionManagerRef = "h2TransactionManager"
)
public class PersistenceH2Configuration {
#Autowired
private Environment env;
#Bean
public LocalContainerEntityManagerFactoryBean h2EntityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(h2DataSource());
em.setPackagesToScan(
new String[] { "com.baeldung.multipledb.model.user" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource h2DataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("h2.jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.h2"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
public PlatformTransactionManager h2TransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
h2EntityManager().getObject());
return transactionManager;
}
**My test class :
**
#ActiveProfile("test")
#SpringBootTest
#Transactional
#DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public class UserRepositoryTests {
#Autowired
#Qualifier("h2EntityManager")
private EntityManger manager;
#UserRepository
private UserRepository userRepo;
// my tests
}
I thought that by specifying a profile, it would work but my tests don't pass since it tries to use my user DB.
I also tried setting the value in my application-test.properties but with no success.
spring.main.allow-bean-definition-overriding=true

How to set initial connections of a dynamic data source

I have a multi-tenant application with multiple datasources. The exact url which its connecting is set by runtime, depending on a request parameter. When I make a request at default 10 database-connections are created. With multiple datasources this fast sums up to a lot of connections. So I want to lower that number and also close the connections after a certain time.
My Configuration Class:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "com.example.demo",
entityManagerFactoryRef = "multiEntityManager",
transactionManagerRef = "multiTransactionManager"
)
public class PersistenceConfiguration extends WebMvcConfigurerAdapter {
private final String PACKAGE_SCAN = "com.example.demo";
//datasources
#Primary
#Bean(name = "COMP1")
public DataSource company1DS() {
return DataSourceBuilder.create()
.username("root")
.password("password")
.url("jdbc:mysql://81.123.456.789:3306/company1")
.build();
}
#Bean(name = "COMP2")
public DataSource company2DS() {
return DataSourceBuilder.create()
.username("root")
.password("password")
.url("jdbc:mysql://81.123.456.789:3306/company2")
.build();
}
#Bean(name = "multiRoutingDataSource")
public DataSource multiRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("COMP1", company1DS());
targetDataSources.put("COMP2", company2DS());
MultiRoutingDataSource multiRoutingDataSource = new MultiRoutingDataSource();
multiRoutingDataSource.setDefaultTargetDataSource(company1DS());
multiRoutingDataSource.setTargetDataSources(targetDataSources);
return multiRoutingDataSource;
}
#Bean(name = "multiEntityManager")
public LocalContainerEntityManagerFactoryBean multiEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(multiRoutingDataSource());
em.setPackagesToScan(PACKAGE_SCAN);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean(name = "multiTransactionManager")
public PlatformTransactionManager multiTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
multiEntityManager().getObject());
return transactionManager;
}
#Primary
#Bean(name = "dbSessionFactory")
public LocalSessionFactoryBean dbSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(multiRoutingDataSource());
sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
return properties;
}
}
What I already tried:
I tried to change the values in the application.properties file like so:
spring.datasource.maxActive=2
spring.datasource.minIdle=2
spring.datasource.maxIdle=5
spring.datasource.initialSize=2
I tried to change the properties the dynamic way (PersistenceConfiguration.hibernateProperties()):
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("spring.datasource.maxActive",2);
properties.put("spring.datasource.minIdle",2);
properties.put("spring.datasource.maxIdle",5);
properties.put("spring.datasource.initialSize",2);
return properties;
}
But it seems that no properties get applied. When I show SHOW GLOBAL STATUS LIKE 'Connections'; in the MySQL workbench, I always get 10 more connections after I made a request from a new datasource.
If there is any important information missing, please let me know and I will add it.
I really appreciate your effort,
Greetings Alexander
EDIT
Since spring.datasource.max-active=2 is not valid, I also tried all the following in application-properties, as well as in the hibernateProperties();
spring.datasource.hikari.maximum-pool-size=2
spring.datasource.tomcat.initial-size=2
spring.datasource.tomcat.max-idle=2
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("spring.datasource.hikari.maximum-pool-size",2);
properties.put("spring.datasource.tomcat.initial-size",2);
properties.put("spring.datasource.tomcat.max-idle",2);
properties.setProperty("spring.datasource.hikari.maximum-pool-size","2");
properties.setProperty("spring.datasource.tomcat.initial-size","2");
properties.setProperty("spring.datasource.tomcat.max-idle","2");
return properties;
}
Nothing changed a thing

Spring Boot: 2 in-memory databases, first one initialized by flyway, second manually

I have two H2 databases in my Spring boot application. Each of these databases is responsible for persistence of different entities.
The first one is initialized by Flyway which works fine, but now I need to initialize the other H2 database. I think I have found out that it is impossible to initialize multiple databases with Flyway. So I am trying to manually import my schema.sql and data.sql files
This is what I have till now:
Two separate DatasourceConfig files:
The first data source config (Notice how this datasource is configured to be primary):
#Configuration
#Profile({"prod","test"})
#EnableJpaRepositories(
basePackages = "tracker.repository.h2",
entityManagerFactoryRef = "h2EntityManager",
transactionManagerRef = "h2TransactionManager")
public class PrivateH2DatasourceConfig {
#Autowired
private Environment env;
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean h2EntityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(h2DataSource());
em.setPackagesToScan(
new String[]{"tracker.domain.h2"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
#Primary
public DataSource h2DataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("h2.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("h2.datasource.url"));
dataSource.setUsername(env.getProperty("h2.datasource.data-username"));
dataSource.setPassword(env.getProperty("h2.datasource.data-password"));
return dataSource;
}
#Bean
#Primary
public PlatformTransactionManager h2TransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(h2EntityManager().getObject());
return transactionManager;
}
}
Second H2 datasource config file:
#Configuration
#Profile("test")
#EnableJpaRepositories(
basePackages = "tracker.repository.wmx",
entityManagerFactoryRef = "wmxH2EntityManager",
transactionManagerRef = "wmxH2TransactionManager")
public class WmxH2DatasourceConfig {
#Autowired
private Environment env;
#Bean
public LocalContainerEntityManagerFactoryBean wmxH2EntityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(wmxH2DataSource());
em.setPackagesToScan(
new String[]{"tracker.domain.wmx"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource wmxH2DataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("test.h2.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("test.h2.datasource.url"));
dataSource.setUsername(env.getProperty("test.h2.datasource.data-username"));
dataSource.setPassword(env.getProperty("test.h2.datasource.data-password"));
return dataSource;
}
#Bean
public PlatformTransactionManager wmxH2TransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(wmxH2EntityManager().getObject());
return transactionManager;
}
}
Then I have application.properties:
#can be over ridden by run arguments
spring.profiles.active=test
flyway.baseline-on-migrate=true
## H2
h2.datasource.driver-class-name=org.h2.Driver
h2.datasource.url=jdbc:h2:./data/deliverytracker.h2
h2.datasource.data-username=x
h2.datasource.data-password=xxx
## H2 WMX (Test environment)
test.h2.datasource.driver-class-name=org.h2.Driver
test.h2.datasource.url=jdbc:h2:./data/wmx_test.h2
test.h2.datasource.data-username=x
test.h2.datasource.data-password=xxx
test.h2.datasource.initialize=true
test.h2.datasource.data=classpath:schema-test.sql,classpath:data-test.sql
and the last line is how I have been trying to import the sql scripts in the correct database, but it doesn't seem to do anything. The first (non-primary) database file is created but it is empty.

spring-boot application doesn't load fixtures into one of multiple data sources

I have some trouble loading data fixtures during start of my spring boot application (1.5.2.RELEASE). The application uses two different database connections, one to our customers postgresql database on which we do not have permissions to create, insert or update anything. The other database is a local embedded h2 database (file). I want to load some data during application start into that h2 database by using the spring boot database initialization phase as described here but the data is never inserted into the h2 database, it stays empty as I can see using squirrel-sql.
This is the configuration in my application.properties:
spring.datasource.abc.driver-class-name=org.postgresql.Driver
spring.datasource.abc.initialize=false
spring.datasource.abc.url=jdbc:postgresql://localhost:5432/abc
spring.datasource.abc.username=abc
spring.datasource.abc.password=abc
spring.datasource.def.driver-class-name=org.h2.Driver
spring.datasource.def.initialize=true
spring.datasource.def.url=jdbc:h2:./${path.prefix}def/def;DB_CLOSE_ON_EXIT=FALSE'
spring.datasource.def.data=classpath:/data-h2.sql
I configured spring boot to use two different databases like described in this stackoverflow post and it all works fine if I pre-insert data by hand into the h2 database.
Configuration of my postgresql datasource:
#Configuration
#EnableJpaRepositories(basePackages = "....abc", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
public class AbcDatabaseConfig
{
#Primary
#Bean
#ConfigurationProperties(prefix = "spring.datasource.abc")
public DataSource dataSource()
{
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("....abc");
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl-auto", "none");
properties.put("hibernate.ejb.entitymanager_factory_name", "entityManagerFactory");
em.setJpaPropertyMap(properties);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
#Primary
#Bean(name = "transactionManager")
public JpaTransactionManager transactionManager(#Qualifier("entityManagerFactory") final EntityManagerFactory factory)
{
return new JpaTransactionManager(factory);
}
}
Configuration of h2-datasource:
#Configuration
#EnableJpaRepositories(basePackages = "....def", entityManagerFactoryRef = "defEntityManagerFactory", transactionManagerRef = "defTransactionManager")
public class InavetDatabaseConfig
{
#Bean
#ConfigurationProperties(prefix = "spring.datasource.def")
public DataSource defDataSource()
{
return DataSourceBuilder.create().build();
}
#Bean(name = "defEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean defEntityManagerFactory()
{
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(defDataSource());
em.setPackagesToScan("....def");
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", "create");
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.ejb.entitymanager_factory_name", "defEntityManagerFactory");
em.setJpaPropertyMap(properties);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
#Bean(name = "defTransactionManager")
public JpaTransactionManager defTransactionManager(
#Qualifier("defEntityManagerFactory") final EntityManagerFactory factory)
{
return new JpaTransactionManager(factory);
}
}
I found out, that only the #Primary marked data sources load fixtures. My workaround for this behaviour is adding code like this to my application:
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(true);
populator.addScript(new PathResource("src/main/resources/data-h2.sql"));
DataSource dataSource = (DataSource) cac.getBean("defDataSource");
DatabasePopulatorUtils.execute(populator, dataSource);
Where cac is the instance of ConfigurableApplicationContext you get as return value by of: SpringApplication.run(,);

Multiple data source and schema creation in Spring Boot

I'm using Spring Boot. I finally managed to setup two data sources, but now I'm facing another issue.
with two data sources in place spring.jpa.hibernate.ddl-auto=create seems to stop working in my spring boot application, only spring.jpa.generate-ddl=true do the job now
I can not manage to select the auto-creation strategy for each of the data sources. I would prefer to create the schema for data source one, and just use the created schema in second DB with data source two.
Any body have idea how to resolve any of these issues? Note I don't want to completely throw away the auto-config if possible. I don't even know yet, if hibernate is able to just initialize schema in one persistence unit.
application.properties
spring.datasource-internal.url=jdbc:hsqldb:mem:testdb
spring.datasource-internal.username=sa
spring.datasource-internal.password=sa
spring.datasource-internal.driver-class-name=org.hsqldb.jdbcDriver
spring.datasource-internal.jpa.database-platform=org.hibernate.dialect.HSQLDialect
spring.datasource-external.url=jdbc:hsqldb:mem:testexternal
spring.datasource-external.username=sa
spring.datasource-external.password=sa
spring.datasource-external.driver-class-name=org.hsqldb.jdbcDriver
spring.datasource-external.jpa.database-platform=org.hibernate.dialect.HSQLDialect
flyway.enabled=false
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
DBInternalConfig
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "cz.data.internal",
entityManagerFactoryRef = "internalEntityManagerFactory",
transactionManagerRef = "internalTransactionManager")
public class DBConfigInternal {
public static final String INTERNAL = "internal";
#Bean(name = "internalDataSource")
#Primary
#ConfigurationProperties(prefix = "spring.datasource-internal")
public DataSource internalDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "internalEntityManagerFactory")
#Primary
public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(internalDataSource())
.packages("cz.data.internal.entity")
.persistenceUnit(INTERNAL)
.build();
}
#Bean(name = "internalTransactionManager")
#Primary
public PlatformTransactionManager internalTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(internalDataSource());
jpaTransactionManager.setPersistenceUnitName(INTERNAL);
return jpaTransactionManager;
}
}
DBExternalConfig
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "cz.data.external",
entityManagerFactoryRef = "externalEntityManagerFactory",
transactionManagerRef = "externalTransactionManager")
public class DBConfigExternal {
public static final String EXTERNAL = "external";
#Bean(name = "externalDataSource")
#ConfigurationProperties(prefix = "spring.datasource-external")
public DataSource externalDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "externalEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean externalEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(externalDataSource())
.packages("cz.data.external.entity")
.persistenceUnit(EXTERNAL)
.build();
}
#Bean(name = "externalTransactionManager")
public PlatformTransactionManager externalTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(externalDataSource());
jpaTransactionManager.setPersistenceUnitName(EXTERNAL);
return jpaTransactionManager;
}
}
M.W.
spring.jpa.hibernate.ddl-auto=create has stopped working, not because you have two DataSources, but because your application's creating its own LocalContainerEntityManagerFactoryBeans. This has the effect of disabling the auto-configuration of a LocalContainerEntityManagerFactoryBean so you now have to configure it yourself.
You can configure the two entity managers to have different schema generation behaviour like this (the first's doing update, the second's doing create):
#Bean(name = "externalEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean externalEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", "update");
return builder
.dataSource(externalDataSource())
.packages("cz.data.external.entity")
.persistenceUnit(EXTERNAL)
.properties(properties)
.build();
}
#Bean(name = "internalEntityManagerFactory")
#Primary
public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", "create");
return builder
.dataSource(internalDataSource())
.packages("cz.data.internal.entity")
.persistenceUnit(INTERNAL)
.properties(properties)
.build();
}

Resources