Spring Boot 2 Multiple Datasources initialize schema - java

I have a Spring Boot 2 application that's using two datasources - one Oracle and one H2. The H2 datasource is set up as secondary, and I want to create the schema for it upon startup, but it never fires off the schema.sql file. This is my Data Source Config file:
#Configuration
public class DataSourceConfig {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean
#ConfigurationProperties("spring.runlogdatasource")
public DataSourceProperties runlogDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.runlogdatasource")
public DataSource runlogDataSource() {
return runlogDataSourceProperties().initializeDataSourceBuilder().build();
}
}
This is my application.properties file:
spring.datasource.url=jdbc:oracle:thin:#my.database.com:1521/mydb
spring.datasource.username=test
spring.datasource.password=ENC(3PXcnoBndLpWN1EcMtmIn+odOwhdWjSrqANijutxuekKEIOco64Jew==)
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.initialization-mode=never
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.maximum-pool-size=10
jasypt.encryptor.bean=stringEncryptor
spring.runlogdatasource.url=jdbc:h2:~/runlogdb;CIPHER=AES;DB_CLOSE_ON_EXIT=FALSE;
spring.runlogdatasource.username=sa
spring.runlogdatasource.password=ENC(3PXcnoBndLpWN1EcMtmIn+odOwhdWjSrqANijutxuekKEIOco64Jew==)
spring.runlogdatasource.driverClassName=org.h2.Driver
spring.runlogdatasource.platform=h2
spring.runlogdatasource.schema=classpath:schema-h2.sql
For the primary datasource, I can see that it enters the DataSourceInitializerInvoker which is where it attempts to load up the schema, but since there are no schema-all.sql files it skips over that one. However, I do have a schema-h2.sql file, but for the secondary datasource it never enters the DataSourceInitializerInvoker and therefore never attempts to initialize the schema. Any help would be greatly appreciated!

This is expected behaviour. When Primary datasource is specified only the schema and data for this datasource is executed. What you need to do in order to have this behavior is to define DataSourceInitializerfor each of the two datasources.
#Bean
public DataSourceInitializer dataSourceInitializer1(#Qualifier("datasource1") DataSource datasource) {
ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
resourceDatabasePopulator.addScript(new ClassPathResource("schema-h22.sql"));
resourceDatabasePopulator.addScript(new ClassPathResource("data-h22.sql"));
DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
dataSourceInitializer.setDataSource(datasource);
dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
return dataSourceInitializer;
}
#Bean
public DataSourceInitializer dataSourceInitializer2(#Qualifier("datasource2") DataSource datasource) {
ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
resourceDatabasePopulator.addScript(new ClassPathResource("schema-h21.sql"));
resourceDatabasePopulator.addScript(new ClassPathResource("data-h21.sql"));
DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
dataSourceInitializer.setDataSource(datasource);
dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
return dataSourceInitializer;
}
You also need to disable the default spring data initialization. You can do this through spring.datasource.initialization-mode=never

Related

Spring Boot/Spring Batch: Using and configuring two DataSource via app properties

I'm working with Spring Boot/Spring Batch, and need to provide two jdbc Data Sources.
I can't find a way to automatically load the config parameters from my application.properties.
//BatchConfiguration which uses both Data Sources:
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
#Bean
public JdbcBatchItemWriter<Customer> writer(#Qualifier("dataSourceOne") DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Customer>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("..."))
.dataSource(dataSource)
.build();
}
#Bean
public JdbcCursorItemReader<Customer> reader(#Qualifier("dataSourceTwo") DataSource dataSource) {
return new JdbcCursorItemReaderBuilder<Customer>()
.dataSource(dataSource)
.name("myItemReader")
.sql("...")
.rowMapper(new CustomerRowMapper())
.build();
}
Above code works with the following Configuration, which has the DataSource provided directly:
//WORKING SOLUTION
#Configuration(proxyBeanMethods = false)
public class DataSourcesConfiguration {
#Bean("dataSourceOne")
#Primary
public DataSource dataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("jdbc:h2:mem:AAA-h2");
dataSourceBuilder.username("AAA");
dataSourceBuilder.password("AAA");
dataSourceBuilder.driverClassName("org.h2.Driver");
return dataSourceBuilder.build();
}
#Bean("dataSourceTwo")
public DataSource dataSourceTwo() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("jdbc:oracle:thin:#AAA");
dataSourceBuilder.username("AAA");
dataSourceBuilder.password("AAA");
dataSourceBuilder.driverClassName("oracle.jdbc.driver.OracleDriver");
return dataSourceBuilder.build();
}
}
Now if I try to create the DataSource from my application properties via annotation #ConfigurationProperties, it will not work:
//NOT WORKING
#Configuration(proxyBeanMethods = false)
public class DataSourcesConfiguration {
#Bean("dataSourceOne")
#Primary
#ConfigurationProperties(prefix="data1.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean("dataSourceTwo")
#ConfigurationProperties(prefix="data2.datasource")
public DataSource dataSourceTwo() {
return DataSourceBuilder.create().build();
}
}
application.properties:
data1.datasource.url=jdbc:h2:mem:AAA-h2
data1.datasource.username=AAA
data1.datasource.password=AAA
data1.datasource.driverClassName=org.h2.Driver
data2.datasource.url=jdbc:oracle:thin:#AAA
data2.datasource.username=AAA
data2.datasource.password=AAA
data2.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
I receive the error Unable to detect database type in the non working version.
How can I correctly configure and provide a DataSource through my properties in application.properties?
The values to use in creating a DataSource are actually part of another class DataSourceProperties
which you can also use to create a DataSource.
Following is a snippet from TaskDbConfig (this class also contains information if you need more functions).
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import com.zaxxer.hikari.HikariDataSource;
#Bean
#ConfigurationProperties("data1.datasource")
public DataSourceProperties data1DataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("data1.datasource.hikari")
public HikariDataSource data1DataSource() {
// Different types are documented at
// https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/jdbc/DataSourceBuilder.html
return data1DataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
application.yml
data1.datasource.platform: h2
data1.datasource.url: 'jdbc:h2:mem:test'
# Hikari config properties: https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby
data1.datasource.hikari.minimumIdle: 1
data1.datasource.hikari.maximumPoolSize: 4

How to connect multiple databases in Spring Boot

I want to develop an application to connect to multiple oracle databases and fetch data from same table from each database.
I have tried using the multiple datasource for every database and fetch the data from the tables.
Resource: https://medium.com/#joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7
DB1 Config:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "CU1EntityManagerFactory", basePackages = {
"com.javatechie.multiple.ds.api.cu1.repository" })
public class CU1Config {
#Primary
#Bean(name = "CU1DataSource")
#ConfigurationProperties(prefix = "spring.cu1.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "CU1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean CU1EntityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("CU1DataSource") DataSource dataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return builder.dataSource(dataSource).properties(properties)
.packages("com.javatechie.multiple.ds.api.model").persistenceUnit("Unit").build();
}
}
DB2 Config:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "CU2EntityManagerFactory", basePackages = {
"com.javatechie.multiple.ds.api.cu2.repository" })
public class CU2Config {
#Bean(name = "CU2DataSource")
#ConfigurationProperties(prefix = "spring.cu2.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "CU2EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean CU2EntityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("CU2DataSource") DataSource dataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return builder.dataSource(dataSource).properties(properties)
.packages("com.javatechie.multiple.ds.api.model").persistenceUnit("Unit").build();
}
}
But the issue that I am facing is for every datasource I have to create a separate config class and also a dedicated repository and service, which is code repeatability though the work from each DB is same to fetch data from a particular table.
And also in future if I want to add any new database I have to repeat the same above process again.
Any help regarding better approach for code reusability is highly appreciated.
You can do it directly through the properties file
spring.datasource.jdbcUrl = [url]
spring.datasource.username = [username]
spring.datasource.password = [password]
spring.second-datasource.jdbcUrl = [url]
spring.second-datasource.username = [username]
spring.second-datasource.password = [password]
Then you need to create the configurations for the datasources:
#Configuration
#PropertySource({"classpath:persistence-multiple-db-boot.properties"})
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager")
public class PersistenceUserAutoConfiguration {
#Primary
#Bean
#ConfigurationProperties(prefix="spring.datasource")
public DataSource userDataSource() {
return DataSourceBuilder.create().build();
}
// userEntityManager bean
// userTransactionManager bean
}
The config for the second one:
#Configuration
#PropertySource({"classpath:persistence-multiple-db-boot.properties"})
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.product",
entityManagerFactoryRef = "productEntityManager",
transactionManagerRef = "productTransactionManager")
public class PersistenceProductAutoConfiguration {
#Bean
#ConfigurationProperties(prefix="spring.second-datasource")
public DataSource productDataSource() {
return DataSourceBuilder.create().build();
}
// productEntityManager bean
// productTransactionManager bean
}
You can find more about this implementation here
If you are going to create a serious service, you should know only how to config them, how to use them, and how to control transaction for all of databases via Spring.
You can see the runnable example and some explanation in https://github.com/surasint/surasint-examples/tree/master/spring-boot-jdbi/10_spring-boot-two-databases (see what you can try in README.txt)
I copied some code here.
First you have to set application.properties like this
#Database
database1.datasource.url=jdbc:mysql://localhost/testdb
database1.datasource.username=root
database1.datasource.password=root
database1.datasource.driver-class-name=com.mysql.jdbc.Driver
database2.datasource.url=jdbc:mysql://localhost/testdb2
database2.datasource.username=root
database2.datasource.password=root
database2.datasource.driver-class-name=com.mysql.jdbc.Driver
Then define them as providers (#Bean) like this:
#Bean(name = "datasource1")
#ConfigurationProperties("database1.datasource")
#Primary
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
#Bean(name = "datasource2")
#ConfigurationProperties("database2.datasource")
public DataSource dataSource2(){
return DataSourceBuilder.create().build();
}
Note that I have #Bean(name="datasource1") and #Bean(name="datasource2"), then you can use it when we need datasource as #Qualifier("datasource1") and #Qualifier("datasource2") , for example
#Qualifier("datasource1")
#Autowired
private DataSource dataSource;
If you do care about transaction, you have to define DataSourceTransactionManager for both of them, like this:
#Bean(name="tm1")
#Autowired
#Primary
DataSourceTransactionManager tm1(#Qualifier ("datasource1") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
#Bean(name="tm2")
#Autowired
DataSourceTransactionManager tm2(#Qualifier ("datasource2") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
Then you can use it like
#Transactional //this will use the first datasource because it is #primary
or
#Transactional("tm2")
The most important part, which you will hardly find an example in anywhere: if you want a method to commit/rollback transactions of both databases, you need ChainedTransactionManager for tm1 and tm2 , like this:
#Bean(name = "chainedTransactionManager")
public ChainedTransactionManager getChainedTransactionManager(#Qualifier ("tm1") DataSourceTransactionManager tm1, #Qualifier ("tm2") DataSourceTransactionManager tm2){
return new ChainedTransactionManager(tm1, tm2);
}
To use it, add this annotation in a method #Transactional(value="chainedTransactionManager") for example
#Transactional(value="chainedTransactionManager")
public void insertAll() {
UserBean test = new UserBean();
test.setUsername("username" + new Date().getTime());
userDao.insert(test);
userDao2.insert(test);
}
This should be enough. See example and detail in the link above.

Spring Session with JDBC - How to Use a Separate DB as a Session Store

I am working on an application that uses Spring Session JDBC. I also am using Spring JPA for other entities. My question is, how does one configure a Spring Boot application to allow for a separate database to be used for Session storage?
I have referenced this question, but it appears the JdbcHttpSessionConfiguration constructor noted in the answer is no longer valid (I am using Spring Boot 2.1.1). Other than that, I was unable to find any documentation on the subject. I found information on how to configure Spring Session with a JDBC backing, and how to use multiple data sources in Spring, but not how to combine the two. I reckon it might involves extending JdbcHttpSessionConfiguration, but unfortunately, I am not able to figure out how to properly do so.
This is all I have thus far:
#Configuration
class SessionConfig extends JdbcHttpSessionConfiguration {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
}
However, the above attempts to create all my entity tables in the H2 store as well.
My primary datasource (PostgreSQL) is specified in my application.properties.
spring.session.store-type=jdbc
spring.datasource.url=jdbc:postgresql://localhost/auth
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.driverClassName=org.postgresql.Driver
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
Thanks for any guidance.
Since Spring Boot 2.0.0 you can specify the DataSource that Spring Session should use by using annotation #SpringSessionDataSource.
Qualifier annotation for a DataSource to be injected in
JdbcOperationsSessionRepository.
The method inside the Spring JdbcHttpSessionConfiguration class that sets the desired datasource.
#Autowired
public void setDataSource(#SpringSessionDataSource ObjectProvider<DataSource> springSessionDataSource, ObjectProvider<DataSource> dataSource)
To achieve the desired result one has to configure a secondary datasource for use in Spring Session and annotate the bean with #SpringSessionDataSource. Below is the configuration that worked for me.
application.properties
session.datasource.url=jdbc:postgresql://localhost:5432/session
session.datasource.driverClassName=org.postgresql.Driver
session.datasource.username=postgres
session.datasource.password=thepassword
primary.datasource.url=jdbc:postgresql://localhost:5432/postgres
primary.datasource.driverClassName=org.postgresql.Driver
primary.datasource.username=postgres
primary.datasource.password=thepassword
The database config
#Configuration
#EnableTransactionManagement
public class DatabaseConfig {
#Bean
#Primary
#ConfigurationProperties("primary.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
#Bean
#ConfigurationProperties("session.datasource")
public DataSourceProperties sessionDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#SpringSessionDataSource
public DataSource springSessionDataSource() {
return sessionDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
}
Remember to run the org/springframework/session/jdbc/schema-thedbplatform.sql schema file on your db if you're not using a embedded database. In my case I ran org/springframework/session/jdbc/schema-postgresql.sql.
If you want to use a H2 database for you session management you can remove the session.datasource... from your application.properties and configure your datasources as follows.
#Configuration
#EnableTransactionManagement
public class DatabaseConfig {
#Bean
#Primary
#ConfigurationProperties("primary.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
#Bean
#SpringSessionDataSource
public EmbeddedDatabase springSessionDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("org/springframework/session/jdbc/schema-h2.sql").build();
}
}

Create metadata tables for Spring Batch in an embedded database

I'm using Spring Boot autoconfigured Spring Batch setup with #EnableBatchProcessing. The problem is that it creates metadata tables in the main database and I don't want this behavior. I would like to save all the Spring Batch information to an embedded database.
I've tried using the spring.batch.initialize-schema=embedded property and adding H2 to the classpath, overriding DefaultBatchConfigurer bean with the H2 data source, replacing JobRepository and JobLauncher beans but it constantly creates metadata tables in the main Oracle database. I'm using Spring Batch 3.0.8 and Spring Boot 1.5.9.
Any help is appreciated, thank you!
UPDATE: Adding come configuration:
H2 config:
#Bean
public DataSource springBatchDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
Oracle:
#Bean
#Primary
public DataSource dataSource() throws SQLException {
PoolDataSourceImpl dataSource = new PoolDataSourceImpl();
dataSource.setConnectionFactoryClassName(environment.getRequiredProperty("db.driverClassName"));
dataSource.setURL(environment.getRequiredProperty("db.url"));
dataSource.setUser(environment.getRequiredProperty("db.username"));
dataSource.setPassword(environment.getRequiredProperty("db.password"));
dataSource.setFastConnectionFailoverEnabled(Boolean.valueOf(environment
.getRequiredProperty("db.fast.connect.failover.enabled")));
dataSource.setValidateConnectionOnBorrow(true);
dataSource.setSQLForValidateConnection("SELECT SYSDATE FROM DUAL");
dataSource.setONSConfiguration(environment.getRequiredProperty("db.ons.config"));
dataSource.setInitialPoolSize(Integer.valueOf(environment.getRequiredProperty("db.initial.pool.size")));
dataSource.setMinPoolSize(Integer.valueOf(environment.getRequiredProperty("db.min.pool.size")));
dataSource.setMaxPoolSize(Integer.valueOf(environment.getRequiredProperty("db.max.pool.size")));
dataSource.setAbandonedConnectionTimeout(120);
dataSource.setInactiveConnectionTimeout(360);
dataSource.setTimeToLiveConnectionTimeout(0);
return dataSource;
}
Batch configuration:
#Configuration
#EnableBatchProcessing
public class BatchConfigurer extends DefaultBatchConfigurer {
#Override
#Autowired
public void setDataSource(#Qualifier("springBatchDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
}
and some properties related..
spring:
batch:
job.enabled: false
1.redefine the BasicBatchConfigurer
2.in spring-boot-batch-starter, you must create your own BatchDataSourceInitializer, so it will execute the init sql scripts
#Configuration
public class MyBatchConfigurer {
#Bean
public BasicBatchConfigurer batchConfigurer(BatchProperties properties,
#Qualifier("springBatchDataSource") DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
return new BasicBatchConfigurer(properties, dataSource,
transactionManagerCustomizers.getIfAvailable());
}
#Bean
public BatchDataSourceInitializer batchDataSourceInitializer(#Qualifier("springBatchDataSource") DataSource dataSource,
ResourceLoader resourceLoader, BatchProperties properties) {
return new BatchDataSourceInitializer(dataSource, resourceLoader,
properties);
}
}
You need to qualify your H2 datasource bean
#Bean(name = "springBatchDataSource")
public DataSource springBatchDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
I hope this help.

How can I read object from one datasource and write to another with spring data?

I have a config class:
#SpringBootConfiguration
#ComponentScan(basePackages = "vap")
public class AppConfig {
Logger logger = LoggerFactory.getLogger(this.getClass());
public AppConfig() {
}
#Bean
public ServerRuntime runtime() {
ServerRuntime runtime = ServerRuntime.builder().addConfig("cayenne-project.xml").build();
return runtime;
}
#Bean
public ObjectContext getContext(#Autowired ServerRuntime serverRuntime) {
return serverRuntime.newContext();
}
#Bean(name = "pgDataSource")
public DataSource getDataSource() {
Properties props = new Properties();
props.setProperty("user", "postgres");
props.setProperty("password", "");
PoolConfiguration configuration = new PoolProperties();
configuration.setDbProperties(props);
configuration.setUrl("jdbc:postgresql://localhost/mikro00");
configuration.setDriverClassName("org.postgresql.Driver");
DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(configuration);
return dataSource;
}
#Bean(name = "hsqldbDataSource")
public DataSource getHSQLDataSource() {
Properties props = new Properties();
props.setProperty("user", "sa");
props.setProperty("password", "");
PoolConfiguration configuration = new PoolProperties();
configuration.setDbProperties(props);
configuration.setUrl("jdbc:h2:file:./outbase");
configuration.setDriverClassName("org.h2.Driver");
DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(configuration);
return dataSource;
}
}
my PGConfig.java
#Configuration
#EnableTransactionManagement
public class PGConfig {
#Primary
#Bean(name = "entityManagerFactoryPG")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, #Qualifier(value = "pgDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean vap = builder.dataSource(dataSource)
.packages("vap")
.build();
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
vap.setJpaVendorAdapter(jpaVendorAdapter);
return vap;
}
#Primary
#Bean(name = "transactionManagerPG")
public PlatformTransactionManager transactionManager(
#Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
My H2Config.java
#Configuration
#EnableTransactionManagement
public class H2Config {
#Primary
#Bean(name = "dataSource")
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, #Qualifier(value = "hsqldbDataSource") DataSource dataSource){
LocalContainerEntityManagerFactoryBean vap = builder.dataSource(dataSource)
.packages("vap")
.build();
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
vap.setJpaVendorAdapter(jpaVendorAdapter);
return vap;
}
#Primary
#Bean(name = "transactionManagerH2")
public PlatformTransactionManager transactionManager(
#Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
KlientRepository
#Repository
public interface KlientRepository extends CrudRepository<Klient,Integer> {
}
How can I read Klient from one repository and write to another. I need to read from PG, work with data and save to h2. I can't find how two object of repository with different datasource, or simply create repository object with concrete datasource
You have pretty much everything out there in your code, you only need to do a bit of fine tuning thats all
Create two configuration classes with bean declaration for Datasource, EntityManagerFactory and TransactionManager
Mark one of the two as primary
Create two model classes(one for each database model)
Create two Repository classes in two different package**(very Important)**
In your service class Autowire both Repositories, read from one DB, manipulate and save to other.
Only thing missing in your code is you need to tell Spring which Repository class should use which EntityManager /Datasource(Since you have two). This can be done by Annotation #EnableJpaRepositories(basepackages=...). Use this annotation on each configuration classes, with basePackages indicating your repository classes

Categories

Resources