foreword
As the business volume increases, some businesses may not be placed in the same database, so the system needs to use multiple databases to fulfill business requirements. We need to configure multiple data sources to operate data in different databases.
text
JdbcTemplate Multiple Data Sources
configure
You need to configure multiple database connections in Spring Boot. Of course, you can decide how to set the key of connection parameters.
It should be noted that there seems to be a problem with
Spring Boot 2.0
the default connection pool configuration parameters of . Since the default connection pool has beenTomcat
changed from toHikariCP
, there was a parameter beforeurl
, which has been changedhikari.jdbcUrl
, otherwise it cannot be registered. The version I'm using below is1.5.9
.
server:
port: 8022
spring:
datasource:
url: jdbc:mysql://localhost:3306/learn?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
second-datasource:
url: jdbc:mysql://localhost:3306/learn1?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123457
driver-class-name: com.mysql.jdbc.Driver
Register DataSource
Register two data sources, register two respectively JdbcTemplate
,
@Configuration
public class DataSourceConfig {
/**
* 注册 data source
*
* @return
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean("firstDataSource")
@Primary // 有相同实例优先选择
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@ConfigurationProperties(prefix = "spring.second-datasource")
@Bean("secondDataSource")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean("firstJdbcTemplate")
@Primary
public JdbcTemplate firstJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
test
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestJDBC {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
@Qualifier("secondJdbcTemplate")
private JdbcTemplate jdbcTemplate1;
@Before
public void before() {
jdbcTemplate.update("DELETE FROM employee");
jdbcTemplate1.update("DELETE FROM employee");
}
@Test
public void testJDBC() {
jdbcTemplate.update("insert into employee(id,name,age) VALUES (1, 'wuwii', 24)");
jdbcTemplate1.update("insert into employee(id,name,age) VALUES (1, 'kronchan', 23)");
Assert.assertThat("wuwii", Matchers.equalTo(jdbcTemplate.queryForObject("SELECT name FROM employee WHERE id=1", String.class)));
Assert.assertThat("kronchan", Matchers.equalTo(jdbcTemplate1.queryForObject("SELECT name FROM employee WHERE id=1", String.class)));
}
}
Using JPA to support multiple data sources
configure
Compared with the use jdbcTemplate
, you need to set JPA
the , and there is not much change:
server:
port: 8022
spring:
datasource:
url: jdbc:mysql://localhost:3306/learn?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
second-datasource:
url: jdbc:mysql://localhost:3306/learn1?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
jpa:
show-sql: true
database: mysql
hibernate:
# update 更新表结构
# create 每次启动删除上次表,再创建表,会造成数据丢失
# create-drop: 每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
# validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
The first thing is that we need to register the corresponding DataSource, and also need to specify Repository
the :
*firstDataSource
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "firstEntityManagerFactory",
transactionManagerRef = "firstTransactionManager",
basePackages = "com.wuwii.module.system.dao" // 设置该数据源对应 dao 层所在的位置
)
public class FirstDataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Primary
@Bean(name = "firstEntityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@ConfigurationProperties(prefix = "spring.datasource")
@Bean("firstDataSource")
@Primary // 有相同实例优先选择,相同实例只能设置唯一
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "firstEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(firstDataSource())
.properties(getVendorProperties(firstDataSource()))
.packages("com.wuwii.module.system.entity") //设置该数据源对应的实体类所在位置
.persistenceUnit("firstPersistenceUnit")
.build();
}
private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Primary
@Bean(name = "firstTransactionManager")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
secondDataSource
:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "secondEntityManagerFactory",
transactionManagerRef = "secondTransactionManager",
basePackages = "com.wuwii.module.user.dao" // 设置该数据源 dao 层所在的位置
)
public class SecondDataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Bean(name = "secondEntityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@ConfigurationProperties(prefix = "spring.second-datasource")
@Bean("secondDataSource")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondDataSource())
.properties(getVendorProperties(secondDataSource()))
.packages("com.wuwii.module.user.entity") //设置该数据源锁对应的实体类所在的位置
.persistenceUnit("secondPersistenceUnit")
.build();
}
private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Bean(name = "secondTransactionManager")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
test
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDemo {
@Autowired
private EmployeeDao employeeDao;
@Autowired
private UserDao userDao;
@Before
public void before() {
employeeDao.deleteAll();
userDao.deleteAll();
}
@Test
public void test() {
Employee employee = new Employee(null, "wuwii", 24);
employeeDao.save(employee);
User user = new User(null, "KronChan", 24);
userDao.save(user);
Assert.assertThat(employee, Matchers.equalTo(employeeDao.findOne(Example.of(employee))));
Assert.assertThat(user, Matchers.equalTo(userDao.findOne(Example.of(user))));
}
}