1.简介
1.1 概述
在实际项目中一般是一个数据源,但是在某些特殊场景可能需要多个数据源,这里以 spring boot jpa 为例演示一下多数据源的配置和使用。
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码
3.1 代码说明
配置两个数据源,分别是 masterDataSource 和 slaveDataSource,它们由两个配置类 MasterConfiguration 和 SlaveConfiguration 来加载,分别扫描不同路径下的 repository。最后通过测试类来调用。
3.2 代码结构
3.3 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3.4 配置文件
application.properties
# master 数据源
spring.datasource.master.jdbc-url=jdbc:mysql://172.16.11.125:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.master.username=root
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
# slave 数据源
spring.datasource.slave.jdbc-url=jdbc:mysql://172.16.11.125:3306/test_jpa?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.slave.username=root
spring.datasource.slave.password=123456
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
# 打印sql、自动建表、格式化sql
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
# 日志打印
logging.level.root=INFO
logging.level.org.hibernate=INFO
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
logging.level.com.soulballad.usage=DEBUG
3.5 java代码
UserModel.java
@Entity
@Table(name = "t_user")
public class UserModel {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, unique = true, length = 32)
private String name;
@Column(nullable = false)
private Integer age;
@Column(length = 32)
private String birthday;
private String address;
@Column(nullable = false, length = 16)
private String phone;
public UserModel() {}
public UserModel(String name, Integer age, String birthday, String address, String phone) {
this.name = name;
this.age = age;
this.birthday = birthday;
this.address = address;
this.phone = phone;
}
// get&set&toString
}
MasterUserRepository.java
@Repository
public interface MasterUserRepository extends JpaRepository<UserModel, Long> {
UserModel findByName(String name);
UserModel findByPhone(String phone);
}
SlaveUserRepository.java
@Repository
public interface SlaveUserRepository extends JpaRepository<UserModel, Long> {
UserModel findByName(String name);
UserModel findByPhone(String phone);
}
DataSourceConfig.java
@Configuration
public class DataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Primary
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "vendorProperties")
public Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
}
MasterConfiguration.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryMaster",
transactionManagerRef = "transactionManagerMaster",
basePackages = "com.soulballad.usage.springboot.repository.master") // repo(dao)所在位置
public class MasterConfiguration {
@Autowired
@Qualifier("masterDataSource")
private DataSource masterDataSource;
@Autowired
@Qualifier("vendorProperties")
private Map<String, Object> vendorProperties;
@Primary
@Bean(name = "entityManagerFactoryMaster")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
return builder.dataSource(masterDataSource).properties(vendorProperties)
.packages("com.soulballad.usage.springboot.model") // 实体类所在位置
.persistenceUnit("masterPersistenceUnit").build();
}
@Primary
@Bean(name = "entityManagerMaster")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryBean(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "transactionManagerMaster")
PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
}
}
SlaveConfiguration.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManageFactorySlave",
transactionManagerRef = "transactionManagerSlave",
basePackages = "com.soulballad.usage.springboot.repository.slave")
public class SlaveConfiguration {
@Autowired
@Qualifier("slaveDataSource")
private DataSource slaveDataSource;
@Autowired
@Qualifier("vendorProperties")
private Map<String, Object> vendorProperties;
@Bean(name = "entityManageFactorySlave")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
return builder.dataSource(slaveDataSource).properties(vendorProperties)
.packages("com.soulballad.usage.springboot.model").persistenceUnit("slavePersistenceUnit").build();
}
@Bean(name = "entityManageSlave")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryBean(builder).getObject().createEntityManager();
}
@Bean(name = "transactionManagerSlave")
PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
}
}
测试类:
UserRepositoryTest.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {
@Autowired
private MasterUserRepository masterUserRepository;
@Autowired
private SlaveUserRepository slaveUserRepository;
@Before
public void save() {
UserModel user1 = new UserModel("zhangsan", 20, "2000-01-01", "shenzhen", "13888888888");
UserModel user2 = new UserModel("lisi", 21, "1999-01-01", "shanghai", "13777777777");
UserModel user3 = new UserModel("wangwu", 22, "1998-01-01", "beijing", "13666666666");
UserModel user4 = new UserModel("zhaoliu", 23, "1997-01-01", "guangzhou", "13555555555");
UserModel user5 = new UserModel("sunqi", 24, "1996-01-01", "wuhan", "13444444444");
List<UserModel> userList = Arrays.asList(user1, user2, user3, user4, user5);
masterUserRepository.saveAll(userList);
slaveUserRepository.saveAll(userList);
}
@Test
public void test_findByName() {
UserModel masterUser = masterUserRepository.findByName("zhangsan");
UserModel slaveUser = slaveUserRepository.findByName("zhangsan");
System.err.println(masterUser);
System.err.println(slaveUser);
}
@Test
public void test_findUserByPhone() {
UserModel masterUser = masterUserRepository.findByPhone("13666666666");
UserModel slaveUser = slaveUserRepository.findByPhone("13666666666");
System.err.println(masterUser);
System.err.println(slaveUser);
}
}
3.6 git 地址
spring-boot/spring-boot-06-jdbc/spring-boot-multi-datasource
4.效果展示
启动 SpringBootMultiDatasourceApplication.main 方法,执行测试类 UserRepositoryTest 中方法,观察结果是否符合预期。
UserRepositoryTest#test_findByName
UserRepositoryTest#test_findByName