To configure multiple data sources in Spring Boot, you can follow the steps below:
1. Define the data source properties for each data source in your `application.properties` or `application.yml` file. For example:
# Data source 1
spring.datasource.url=jdbc:mysql://localhost:3306/database1
spring.datasource.username=username1
spring.datasource.password=password1
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# Data source 2
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/database2
spring.datasource.secondary.username=username2
spring.datasource.secondary.password=password2
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
2. Create a configuration class for each data source, which extends `org.springframework.boot.autoconfigure.jdbc.DataSourceProperties`. For example:
@Configuration
@PropertySource(“classpath:application.properties”)
@EnableTransactionManagement
public class DataSourceConfig1 extends DataSourceProperties {
@Bean(name = “dataSource1”)
public DataSource dataSource() {
return DataSourceBuilder.create()
.driverClassName(getDriverClassName())
.url(getUrl())
.username(getUsername())
.password(getPassword())
.build();
}
}
@Configuration
@PropertySource(“classpath:application.properties”)
@EnableTransactionManagement
public class DataSourceConfig2 extends DataSourceProperties {
@Bean(name = “dataSource2”)
public DataSource dataSource() {
return DataSourceBuilder.create()
.driverClassName(getDriverClassName())
.url(getSecondaryUrl())
.username(getSecondaryUsername())
.password(getSecondaryPassword())
.build();
}
}
3. Configure the `@Primary` and `@Qualifier` annotations to define which data source to use when multiple data sources are available. For example:
@Configuration
public class JpaConfig {
@Autowired
@Qualifier(“dataSource1”)
private DataSource dataSource1;
@Autowired
@Qualifier(“dataSource2”)
private DataSource dataSource2;
@Primary
@Bean(name = “entityManagerFactory1”)
public LocalContainerEntityManagerFactoryBean entityManagerFactory1(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource1)
.packages(“com.example.domain1”)
.persistenceUnit(“domain1”)
.build();
}
@Bean(name = “entityManagerFactory2”)
public LocalContainerEntityManagerFactoryBean entityManagerFactory2(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource2)
.packages(“com.example.domain2”)
.persistenceUnit(“domain2”)
.build();
}
@Primary
@Bean(name = “transactionManager1”)
public PlatformTransactionManager transactionManager1(@Qualifier(“entityManagerFactory1”) EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
@Bean(name = “transactionManager2”)
public PlatformTransactionManager transactionManager2(@Qualifier(“entityManagerFactory2”) EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
4. Finally, use the `@Autowired` annotation to inject the appropriate data source and transaction manager for each entity manager. For example:
@Service
public class MyService {
@Autowired
@Qualifier(“entityManagerFactory1”)
private EntityManagerFactory entityManagerFactory1;
@Autowired
@Qualifier(“transactionManager1”)
private PlatformTransactionManager transactionManager1;
// Use entityManagerFactory1 and transactionManager1 to interact with domain1
@Autowired
@Qualifier(“entityManagerFactory2”)
private EntityManagerFactory entityManagerFactory2;
@Autowired
@Qualifier(“transactionManager2”)
private PlatformTransactionManager transactionManager2;
Sample code to use entity manager and transaction manager to retrieve data
Assuming you have defined your entity classes and JPA repositories, here is an example of how to use the entity manager and transaction manager to retrieve data:
@Service
public class MyService {
@Autowired
@Qualifier(“entityManagerFactory1”)
private EntityManagerFactory entityManagerFactory1;
@Autowired
@Qualifier(“transactionManager1”)
private PlatformTransactionManager transactionManager1;
@Autowired
private MyEntityRepository1 myEntityRepository1;
public void doSomething() {
// Create a transaction for entity manager 1
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
TransactionStatus transactionStatus = transactionManager1.getTransaction(transactionDefinition);
try {
// Get the entity manager for domain1
EntityManager entityManager1 = entityManagerFactory1.createEntityManager();
// Retrieve some data using a JPA repository for domain1
List<MyEntity1> myEntities1 = myEntityRepository1.findAll();
// Do something with the data
for (MyEntity1 myEntity1 : myEntities1) {
System.out.println(myEntity1.toString());
}
// Commit the transaction
transactionManager1.commit(transactionStatus);
} catch (Exception ex) {
// Roll back the transaction if an exception occurs
transactionManager1.rollback(transactionStatus);
throw ex;
}
}
}
In this example, `MyEntityRepository1` is a JPA repository interface for domain1 that extends `JpaRepository<MyEntity1, Long>`. The `findAll()` method is provided by the `JpaRepository` interface and returns all entities of type `MyEntity1` in the database.
Leave a Reply