廈門(mén)網(wǎng)站建設(shè)公司新網(wǎng)域名
配置數(shù)據(jù)源實(shí)際上就是配置多個(gè)數(shù)據(jù)庫(kù),在一個(gè)配置文件中配置多個(gè)數(shù)據(jù)庫(kù),這樣做主要的好處有以下幾點(diǎn):
- 數(shù)據(jù)庫(kù)隔離:通過(guò)配置多個(gè)數(shù)據(jù)源,可以將不同的業(yè)務(wù)數(shù)據(jù)存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中,實(shí)現(xiàn)數(shù)據(jù)的隔離。這樣可以提高系統(tǒng)的安全性和穩(wěn)定性,避免不同業(yè)務(wù)之間的數(shù)據(jù)相互干擾。
- 性能優(yōu)化:通過(guò)配置多個(gè)數(shù)據(jù)源,可以將讀寫(xiě)操作分離到不同的數(shù)據(jù)庫(kù)中,從而提高系統(tǒng)的并發(fā)性能。例如,將讀操作集中在一個(gè)主數(shù)據(jù)庫(kù)中,將寫(xiě)操作分散到多個(gè)從數(shù)據(jù)庫(kù)中,可以有效地減輕數(shù)據(jù)庫(kù)的讀寫(xiě)壓力,提高系統(tǒng)的響應(yīng)速度。
- 擴(kuò)展性:當(dāng)系統(tǒng)需要擴(kuò)展到多個(gè)地理位置或多個(gè)數(shù)據(jù)中心時(shí),配置多個(gè)數(shù)據(jù)源可以更好地支持分布式部署。每個(gè)地理位置或數(shù)據(jù)中心可以配置一個(gè)獨(dú)立的數(shù)據(jù)源,使得數(shù)據(jù)訪(fǎng)問(wèn)更加高效和可靠。
- 多租戶(hù)支持:對(duì)于多租戶(hù)的系統(tǒng),配置多個(gè)數(shù)據(jù)源可以實(shí)現(xiàn)不同租戶(hù)的數(shù)據(jù)隔離。每個(gè)租戶(hù)可以擁有自己獨(dú)立的數(shù)據(jù)庫(kù),從而保證數(shù)據(jù)的安全性和隱私性。
- 數(shù)據(jù)庫(kù)版本升級(jí):在進(jìn)行數(shù)據(jù)庫(kù)版本升級(jí)時(shí),可以通過(guò)配置多個(gè)數(shù)據(jù)源,將新版本的數(shù)據(jù)庫(kù)與舊版本的數(shù)據(jù)庫(kù)并行使用。這樣可以在升級(jí)過(guò)程中保證系統(tǒng)的正常運(yùn)行,減少升級(jí)帶來(lái)的風(fēng)險(xiǎn)。
我們目前常用的三種數(shù)據(jù)訪(fǎng)問(wèn)方法方式:
- JDBCTemplate
- Spring Data JPA
- MyBatis
接下來(lái)我們將圍繞這種數(shù)據(jù)訪(fǎng)問(wèn)方法進(jìn)行配置:
JDBCTemplate
實(shí)際上這種方式,主要還是在application.properties中設(shè)置我們需要鏈接的數(shù)據(jù)庫(kù)配置,比如我A數(shù)據(jù)庫(kù)用來(lái)存儲(chǔ)用戶(hù)信息,B數(shù)據(jù)庫(kù)用來(lái)存儲(chǔ)業(yè)務(wù)數(shù)據(jù)。
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
ok,我們繼續(xù)配置完畢后數(shù)據(jù)源后,我們就通過(guò)配置類(lèi)來(lái)完成加載這些配置信息,初始話(huà)數(shù)據(jù)源,以及初始化每個(gè)數(shù)據(jù)源的時(shí)候要用的JDBCTemplate。你只需要在你的Spring Boot中應(yīng)用下面的配置類(lèi)就可以完成。
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}@Beanpublic JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {return new JdbcTemplate(primaryDataSource);}@Beanpublic JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {return new JdbcTemplate(secondaryDataSource);}}
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
單元測(cè)試類(lèi):
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprotected JdbcTemplate primaryJdbcTemplate;@Autowiredprotected JdbcTemplate secondaryJdbcTemplate;@Beforepublic void setUp() {primaryJdbcTemplate.update("DELETE FROM USER ");secondaryJdbcTemplate.update("DELETE FROM USER ");}@Testpublic void test() throws Exception {// 往第一個(gè)數(shù)據(jù)源中插入 2 條數(shù)據(jù)primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);// 往第二個(gè)數(shù)據(jù)源中插入 1 條數(shù)據(jù),若插入的是第一個(gè)數(shù)據(jù)源,則會(huì)主鍵沖突報(bào)錯(cuò)secondaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);// 查一下第一個(gè)數(shù)據(jù)源中是否有 2 條數(shù)據(jù),驗(yàn)證插入是否成功Assert.assertEquals("2", primaryJdbcTemplate.queryForObject("select count(1) from user", String.class));// 查一下第一個(gè)數(shù)據(jù)源中是否有 1 條數(shù)據(jù),驗(yàn)證插入是否成功Assert.assertEquals("1", secondaryJdbcTemplate.queryForObject("select count(1) from user", String.class));}
}
有兩個(gè)JdbcTemplate,為什么不用@Qualifier指定?這里順帶說(shuō)個(gè)小知識(shí)點(diǎn),當(dāng)我們不指定的時(shí)候,會(huì)采用參數(shù)的名字來(lái)查找Bean,存在的話(huà)就注入。
這兩個(gè)JdbcTemplate創(chuàng)建的時(shí)候,我們也沒(méi)指定名字,它們是如何匹配上的?這里也是一個(gè)小知識(shí)點(diǎn),當(dāng)我們創(chuàng)建Bean的時(shí)候,默認(rèn)會(huì)使用方法名稱(chēng)來(lái)作為Bean的名稱(chēng),所以這里就對(duì)應(yīng)上了。讀者不妨回頭看看兩個(gè)名稱(chēng)是不是一致的。
Spring Data JPA
和上邊那種方式基本上類(lèi)似,所做的操作會(huì)有細(xì)微的區(qū)別。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
配置application.properties文件
# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver# 日志打印執(zhí)行的SQL
spring.jpa.show-sql=true
# Hibernate的DDL策略
spring.jpa.hibernate.ddl-auto=create-drop
創(chuàng)建實(shí)體類(lèi):
@Entity
//@Data
//@NoArgsConstructor
public class User {@Id@GeneratedValueprivate Long id;private String name;private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public User() {}
}
public interface UserRepository extends JpaRepository<User, Long> {}
@Entity
//@Data
//@NoArgsConstructor
public class Message {@Id@GeneratedValueprivate Long id;private String title;private String message;public Message(String title, String message) {this.title = title;this.message = message;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Message() {}
}
public interface MessageRepository extends JpaRepository<Message, Long> {}
多數(shù)據(jù)源配置類(lèi):
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}}
主數(shù)據(jù)源配置類(lèi):
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactoryPrimary",transactionManagerRef="transactionManagerPrimary",basePackages= { "com.miaow.demo.p" }) //設(shè)置Repository所在位置
public class PrimaryConfig {@Autowired@Qualifier("primaryDataSource")private DataSource primaryDataSource;@Autowiredprivate JpaProperties jpaProperties;@Autowiredprivate HibernateProperties hibernateProperties;private Map<String, Object> getVendorProperties() {return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());}@Primary@Bean(name = "entityManagerPrimary")public EntityManager entityManager(EntityManagerFactoryBuilder builder) {return entityManagerFactoryPrimary(builder).getObject().createEntityManager();}@Primary@Bean(name = "entityManagerFactoryPrimary")public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
// HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
// jpaVendorAdapter.setGenerateDdl(true);return builder.dataSource(primaryDataSource).packages("com.miaow.demo.p") //設(shè)置實(shí)體類(lèi)所在位置.persistenceUnit("primaryPersistenceUnit").properties(getVendorProperties()).build();}@Primary@Bean(name = "transactionManagerPrimary")public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());}
}
設(shè)置從數(shù)據(jù)庫(kù)配置類(lèi):
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactorySecondary",transactionManagerRef="transactionManagerSecondary",basePackages= { "com.miaow.demo.s" }) //設(shè)置Repository所在位置
public class SecondaryConfig {@Autowired@Qualifier("secondaryDataSource")private DataSource secondaryDataSource;@Autowiredprivate JpaProperties jpaProperties;@Autowiredprivate HibernateProperties hibernateProperties;private Map<String, Object> getVendorProperties() {return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());}@Bean(name = "entityManagerSecondary")public EntityManager entityManager(EntityManagerFactoryBuilder builder) {return entityManagerFactorySecondary(builder).getObject().createEntityManager();}@Bean(name = "entityManagerFactorySecondary")public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {return builder.dataSource(secondaryDataSource).packages("com.miaow.demo.s") //設(shè)置實(shí)體類(lèi)所在位置.persistenceUnit("secondaryPersistenceUnit").properties(getVendorProperties()).build();}@Bean(name = "transactionManagerSecondary")PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());}}
創(chuàng)建的單元測(cè)試:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprivate UserRepository userRepository;@Autowiredprivate MessageRepository messageRepository;@Testpublic void test() throws Exception {userRepository.save(new User("aaa", 10));userRepository.save(new User("bbb", 20));userRepository.save(new User("ccc", 30));userRepository.save(new User("ddd", 40));userRepository.save(new User("eee", 50));Assert.assertEquals(5, userRepository.findAll().size());messageRepository.save(new Message("o1", "aaaaaaaaaa"));messageRepository.save(new Message("o2", "bbbbbbbbbb"));messageRepository.save(new Message("o3", "cccccccccc"));Assert.assertEquals(3, messageRepository.findAll().size());}}
MyBatis
在Spring Boot的配置文件application.properties中設(shè)置我們需要的兩個(gè)連接的數(shù)據(jù)庫(kù)配置:
# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver#mybatis.mapper-locations=classpath:mapper/*.xml
創(chuàng)建一個(gè)初始化多數(shù)據(jù)源和MyBatis配置
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}}
可以看到內(nèi)容跟JdbcTemplate
、Spring Data JPA
的時(shí)候是一模一樣的。通過(guò)@ConfigurationProperties
可以知道這兩個(gè)數(shù)據(jù)源分別加載了spring.datasource.primary.*
和spring.datasource.secondary.*
的配置。@Primary
注解指定了主數(shù)據(jù)源,就是當(dāng)我們不特別指定哪個(gè)數(shù)據(jù)源的時(shí)候,就會(huì)使用這個(gè)Bean真正差異部分在下面的JPA配置上。
分別創(chuàng)建這兩個(gè)數(shù)據(jù)源的MyBatis配置文件:
Private 數(shù)據(jù)源的JPA的配置文件:
@Configuration
@MapperScan(basePackages = "com.miaow.demo.p",sqlSessionFactoryRef = "sqlSessionFactoryPrimary",sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
public class PrimaryConfig {private DataSource primaryDataSource;public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {this.primaryDataSource = primaryDataSource;}@Beanpublic SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(primaryDataSource);return bean.getObject();}@Beanpublic SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {return new SqlSessionTemplate(sqlSessionFactoryPrimary());}}
Secondary的數(shù)據(jù)源JPA配置:
@Configuration
@MapperScan(basePackages = "com.miaow.demo.s",sqlSessionFactoryRef = "sqlSessionFactorySecondary",sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
public class SecondaryConfig {private DataSource secondaryDataSource;public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {this.secondaryDataSource = secondaryDataSource;}@Beanpublic SqlSessionFactory sqlSessionFactorySecondary() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(secondaryDataSource);return bean.getObject();}@Beanpublic SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {return new SqlSessionTemplate(sqlSessionFactorySecondary());}}
注意在此說(shuō)明一下,配置類(lèi)上使用@MapperScan
注解來(lái)指定當(dāng)前數(shù)據(jù)源下定義的Entity
和Mapper
的包路徑;
另外需要指定sqlSessionFactory
和sqlSessionTemplate
,這兩個(gè)具體實(shí)現(xiàn)在該配置類(lèi)中類(lèi)中初始化。
配置類(lèi)的構(gòu)造函數(shù)中,通過(guò)@Qualifier
注解來(lái)指定具體要用哪個(gè)數(shù)據(jù)源,其名字對(duì)應(yīng)在DataSourceConfiguration
配置類(lèi)中的數(shù)據(jù)源定義的函數(shù)名。
配置類(lèi)中定義SqlSessionFactory
和SqlSessionTemplate
的實(shí)現(xiàn),注意具體使用的數(shù)據(jù)源正確。
創(chuàng)建一個(gè)UserPrimary實(shí)體類(lèi):
public class UserPrimary {private Long id;private String name;private Integer age;public UserPrimary(String name, Integer age) {this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public UserPrimary() {}
}
創(chuàng)建一個(gè)UserMapperPrimary用來(lái)作為填寫(xiě)SQL語(yǔ)句的接口:
public interface UserMapperPrimary {@Select("SELECT * FROM USER WHERE NAME = #{name}")UserPrimary findByName(@Param("name") String name);@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);@Delete("DELETE FROM USER")int deleteAll();}
創(chuàng)建一個(gè)UserSecondary實(shí)體類(lèi):
public class UserSecondary {private Long id;private String name;private Integer age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public UserSecondary() {}public UserSecondary(String name, Integer age) {this.name = name;this.age = age;}
}
public interface UserMapperSecondary {@Select("SELECT * FROM USER WHERE NAME = #{name}")UserSecondary findByName(@Param("name") String name);@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);@Delete("DELETE FROM USER")int deleteAll();
}
之后,也是最關(guān)鍵的一步,我們需要在MyBatis的配置文件中使用Mapper.xml
在Resources目錄下創(chuàng)建一個(gè)mapper文件夾,之后再mapper文件夾下邊分別創(chuàng)建primary和secondary文件夾:
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.miaow.demo.p.mapper.UserMapperPrimary"><select id="findByName" resultType="com.miaow.demo.p.entity.UserPrimary">SELECT * FROM USER WHERE NAME = #{name}</select><insert id="insert">INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})</insert></mapper>
與上邊這個(gè)幾乎一樣,只是兩者指向的接口位置不一樣:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.miaow.demo.s.mapper.UserMapperSecondary"><select id="findByName" resultType="com.miaow.demo.s.entity.UserSecondary">SELECT * FROM USER WHERE NAME = #{name}</select><insert id="insert">INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})</insert></mapper>
最后我們可以通過(guò)一個(gè)測(cè)試類(lèi)進(jìn)行測(cè)試:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class ApplicationTests {//第一數(shù)據(jù)庫(kù)配置類(lèi)@Autowiredprivate UserMapperPrimary userMapperPrimary;//第二數(shù)據(jù)庫(kù)配置文件@Autowiredprivate UserMapperSecondary userMapperSecondary;@Beforepublic void setUp() {// 清空測(cè)試表,保證每次結(jié)果一樣userMapperPrimary.deleteAll();userMapperSecondary.deleteAll();}@Testpublic void test() throws Exception {// 往Primary數(shù)據(jù)源插入一條數(shù)據(jù)userMapperPrimary.insert("AAA", 20);// 從Primary數(shù)據(jù)源查詢(xún)剛才插入的數(shù)據(jù),配置正確就可以查詢(xún)到UserPrimary userPrimary = userMapperPrimary.findByName("AAA");Assert.assertEquals(20, userPrimary.getAge().intValue());// 從Secondary數(shù)據(jù)源查詢(xún)剛才插入的數(shù)據(jù),配置正確應(yīng)該是查詢(xún)不到的UserSecondary userSecondary = userMapperSecondary.findByName("AAA");Assert.assertNull(userSecondary);// 往Secondary數(shù)據(jù)源插入一條數(shù)據(jù)userMapperSecondary.insert("BBB", 20);// 從Primary數(shù)據(jù)源查詢(xún)剛才插入的數(shù)據(jù),配置正確應(yīng)該是查詢(xún)不到的userPrimary = userMapperPrimary.findByName("BBB");Assert.assertNull(userPrimary);// 從Secondary數(shù)據(jù)源查詢(xún)剛才插入的數(shù)據(jù),配置正確就可以查詢(xún)到userSecondary = userMapperSecondary.findByName("BBB");Assert.assertEquals(20, userSecondary.getAge().intValue());}}