I want to work with two databases in Spring Boot, - some models go to db1, others to db2
But how can i swap between them, or tell which repo belongs to which db?
# db1
spring.datasource.url=connectionString
spring.datasource.username=db1
spring.datasource.password=***
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
# db2
spring.datasource.url=connectionString
spring.datasource.username=db2
spring.datasource.password=***
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
You are using the same property to define two distinguished datasources, which is incorrect. You have to define your two datasources properties for example :
spring.postgresql.datasource.url=jdbc:postgresql://localhost:5432/book_db
spring.postgresql.datasource.username=postgres
spring.postgresql.datasource.password=postgres
spring.postgresql.datasource.driver-class-name=org.postgresql.Driver
spring.mysql.datasource.url=jdbc:mysql://localhost:3306/author_db?autoReconnect=true&useSSL=false
spring.mysql.datasource.username=root
spring.mysql.datasource.password=
spring.mysql.datasource.driver-class-name=com.mysql.jdbc.Driver
And then in your Spring configuration define the datasources. For example :
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.postgresql.datasource")
public DataSource postgresqlDataSource() {
return DataSourceBuilder
.create()
.build();
}
And
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.mysql.datasource")
public DataSource mysqlDataSource() {
return DataSourceBuilder
.create()
.build();
}
Follow this tutorial to have further information.
Related
I am currently working on a project which is using Redis mainly for caching purposes, I am using Oracle as the main database and Spring Data JPA to handle the database layer in my project. I need to know how to use #Transactional annotation support to handle transactions in Redis. I have already referred to lots of tutorials and documentation regarding this scenario. In most of those tutorials, there is always the same set of source codes available. But still, I didn't have a clear idea about the implementation. Because in my application there is already a data source available which I configured through property file. (Oracle database) So I doubt the implementation of the dataSource bean. And I couldn't understand the usage of transactionManager bean too. How should I implement this properly please give a detailed explanation.
Source code which I found on the internet.
#Configuration
#EnableTransactionManagement // 1
public class RedisConfig {
#Bean
public StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {
// Configure redisTemplate
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
/ / Open transaction support
stringRedisTemplate.setEnableTransactionSupport(true); // 2
return stringRedisTemplate;
}
#Bean
public PlatformTransactionManager transactionManager() throws SQLException {
return new DataSourceTransactionManager(dataSource()); // 3
}
#Bean
public DataSource dataSource() throws SQLException {
// ...
}
}
Updated :
Currently configured datasource properties in apppication.properties file.
# OracleDB connection settings
spring.datasource.url=jdbc:oracle:thin:#192.168.20.108:1521:orcl
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
# HikariCP settings
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.poolName=redis-sample-pool
Resource about the Redis Transactions handling
There're two ways to configure DataSource
Using the config file
spring.datasource.url= jdbc:oracle:thin:#//localhost
spring.datasource.username=test
spring.datasource.password=test1234
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
#hibernate config dialect for JPA, choose dialect based on the db version
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
You can create manually the same by reading these properties, with the help of DataSourceBuilder
#Bean
public DataSource dataSource(){
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("oracle.jdbc.OracleDriver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("test");
dataSourceBuilder.password("test1234");
return dataSourceBuilder.build();
}
I've created a pretty standard Spring Boot 2.0 app with Services and Repositories to access a database.
I had to set the standard Spring Boot application properties to get it to work, such as:
spring.datasource.url, spring.jpa.database, etc.
However, in order to prevent my properties from overwriting other properties in similar apps hosted in the same place, I need to rename these properties, such as:
myApp.spring.datasource.url, myApp.spring.jpa.database, etc.
Some of these properties will be set by environmental variables instead of the application.properties file.
However, I can't see any way to override those variables in my app.
The standard approach is to use #Value to configure those variables. However, the Spring Boot 2.0 setup for services looks up all these properties "behind the scenes," so that doesn't appear to be an option here.
Is there any way to configure my app to read all those myApp.common.property.name properties and treat them as common.property.name?
Thank you.
Yes, the standard way is to use #Value. But thw work doesn't stop there, you need to create DataSource and EntityManager with these values.
Springboot will create DataSource, Entitymanager and some other components bey looking into default properties(spring.xxx) from the file(hence Spring boot is opinionated). But when you change these names to non default values, then you need to create these components / beans yourself.
Instead of using #Value you could also use #Configurationproperties. #Value also works but you might need to declare like 6 or 7 values with #Value. If you wish to use #ConfigurationProperties, make sure you have #EnableConfigurationProperties annotation added somewhere in your project.
Here is a code snippet. You need to tune it to your project
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactory",
basePackages = { "com.xxx.yyy.repo" }
)
public class SomeDbConfig {
#Primary // Use this if you have multiple datasources or else no use
#Bean(name = "dataSource")
#ConfigurationProperties(prefix = "myApp.spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean
entityManagerFactory(
EntityManagerFactoryBuilder builder,
#Qualifier("dataSource") DataSource dataSource
) {
return builder
.dataSource(dataSource)
.packages("com.xxx.yyy.domain")
.persistenceUnit("somename")
.build();
}
#Primary
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
#Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
I need to change my connection with the Database in runtime. For Example, if parameter requested is BD1, connect on database 1, if BD2, connect in database 2, etc.
I am using spring boot. What is the best way for this.
I have this #Configuration, but not know to say my repository how to use.
#Configuration
public class DataSourceConfiguration {
#Bean(name = "ccteste")
#ConfigurationProperties("spring.ciclocairu.teste.datasource")
#Primary
public DataSource ciclocairuTeste() {
return DataSourceBuilder.create().build();
}
#Bean(name = "ccprod")
#ConfigurationProperties("spring.ciclocairu.prod.datasource")
public DataSource ciclocairuProd() {
return DataSourceBuilder.create().build();
}
#Bean(name = "tmccteste")
#Autowired
#Primary
DataSourceTransactionManager transactionManagerCicloCairuTeste(#Qualifier("ccteste") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
#Bean(name = "tmccprod")
#Autowired
#Primary
DataSourceTransactionManager transactionManagerCicloCairuProd(#Qualifier("ccprod") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
}
Looks like you are looking for some data source routing. Spring has AbstractRoutingDataSource for run-time detection what data source should be used.
Abstract DataSource implementation that routes getConnection() calls
to one of various target DataSources based on a lookup key.
Also you can set default datasource by setDefaultTargetDataSource method.
It works in such way: you put data sources that you need in a map in AbstractRoutingDataSource at the bean configuration stage, and when you need to use a specific data source you put the key for this source into the context that linked to the router. This ds-key is linked to the current thread.
Here are examples : Dynamic DataSource Routing with Spring and Spring DataSource Routing
Might take a look at my answer at Manage transactions with multiple datasource, entity managers for same application code
or my blog post: Multi-tenant applications using Spring Boot, JPA, Hibernate and Postgres
I am running a Spring Batch job and have two DataSource's configured like such:
#Bean
#Primary
#ConfigurationProperties(prefix="spring.datasource")
public DataSource mainDataSource() {
return DataSourceBuilder.create().build();
}
#Bean("SpringBatchDataSource")
#ConfigurationProperties(prefix="spring.batch.datasource")
public DataSource batchDataSource() {
return DataSourceBuilder.create().build();
}
As you can see of the two DataSources I have one is just for the Spring batch metadata.
This issue I'm having is Spring batch wants to use the #Primary DataSource. How can I configure it to use the batchDataSource?
I am just learning how to use springboot as a java backend framework and I currently have applications.properties configured to use 1 database.
I am thinking of adding an additional database to store different information instead of saving everything on a single database so I was wondering how (if possible) can i do that?
My application.properties file contains data like this:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://database:3306...
Any ideas?
You can create two datasources, one bean of them mark as #Primary
#Bean
#ConfigurationProperties(prefix = "datasource.mysql")
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
#ConfigurationProperties(prefix = "datasource.postgres")
#Bean
#Primary
public DataSource postgresDataSource() {
return DataSourceBuilder.create().
build();
}
Your application.properties should looks like this:
datasource.mysql.url=jdbc:mysql://localhost:3306/mysql_demo
datasource.mysql.username=root
datasource.mysql.password=root
datasource.mysql.driverClassName=com.mysql.jdbc.Driver
datasource.postgres.url=jdbc:postgresql://localhost:5432/postgres_demo
datasource.postgres.username=postgres
datasource.postgres.password=postgres
datasource.postgres.driverClassName=org.postgresql.Driver