SpringBoot整合Mybatis相关-SpringBoot2.x——MyBatis的多数据源配置-《Java笔记》

admin 2025-10-19 05:13:09 编程 来源:ZONE.CI 全球网 0 阅读模式

Java SpringBoot Mybatis

添加多数据源的配置

先在Spring Boot的配置文件application.properties中设置两个要链接的数据库配置,比如这样:

  1. spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
  2. spring.datasource.primary.username=root
  3. spring.datasource.primary.password=123456
  4. spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
  5. spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
  6. spring.datasource.secondary.username=root
  7. spring.datasource.secondary.password=123456
  8. spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver

说明与注意:

  1. 多数据源配置的时候,与单数据源不同点在于spring.datasource之后多设置一个数据源名称primary和secondary来区分不同的数据源配置,这个前缀将在后续初始化数据源的时候用到。
  2. 数据源连接配置2.x和1.x的配置项是有区别的:2.x使用spring.datasource.secondary.jdbc-url,而1.x版本使用spring.datasource.secondary.url。如果在配置的时候发生了这个报错java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.,那么就是这个配置项的问题。
  3. 可以看到,不论使用哪一种数据访问框架,对于数据源的配置都是一样的。

    初始化数据源与MyBatis配置

    完成多数据源的配置信息之后,就来创建个配置类来加载这些配置信息,初始化数据源,以及初始化每个数据源要用的MyBatis配置。这里继续将数据源与框架配置做拆分处理:

    单独建一个多数据源的配置类,比如下面这样:

    ```java @Configuration public class DataSourceConfiguration {

    @Primary @Bean @ConfigurationProperties(prefix = “spring.datasource.primary”) public DataSource primaryDataSource() {

    1. return DataSourceBuilder.create().build();

    }

    @Bean @ConfigurationProperties(prefix = “spring.datasource.secondary”) public DataSource secondaryDataSource() {

    1. return DataSourceBuilder.create().build();

    }

}

  1. 可以看到内容跟JdbcTemplateSpring Data JPA的时候是一模一样的。通过`@ConfigurationProperties`可以知道这两个数据源分别加载了`spring.datasource.primary.*``spring.datasource.secondary.*`的配置。`@Primary`注解指定了主数据源,就是当不特别指定哪个数据源的时候,就会使用这个Bean真正差异部分在下面的JPA配置上。
  2. <a name="wZUxl"></a>
  3. ### 分别创建两个数据源的MyBatis配置。
  4. <a name="grtlL"></a>
  5. #### Primary数据源的JPA配置:
  6. ```java
  7. @Configuration
  8. @MapperScan(
  9. basePackages = "com.didispace.chapter39.p",
  10. sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
  11. sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
  12. public class PrimaryConfig {
  13. private DataSource primaryDataSource;
  14. public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
  15. this.primaryDataSource = primaryDataSource;
  16. }
  17. @Bean
  18. public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
  19. SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
  20. bean.setDataSource(primaryDataSource);
  21. return bean.getObject();
  22. }
  23. @Bean
  24. public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
  25. return new SqlSessionTemplate(sqlSessionFactoryPrimary());
  26. }
  27. }

Secondary数据源的JPA配置:

  1. @Configuration
  2. @MapperScan(
  3. basePackages = "com.didispace.chapter39.s",
  4. sqlSessionFactoryRef = "sqlSessionFactorySecondary",
  5. sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
  6. public class SecondaryConfig {
  7. private DataSource secondaryDataSource;
  8. public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
  9. this.secondaryDataSource = secondaryDataSource;
  10. }
  11. @Bean
  12. public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
  13. SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
  14. bean.setDataSource(secondaryDataSource);
  15. return bean.getObject();
  16. }
  17. @Bean
  18. public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {
  19. return new SqlSessionTemplate(sqlSessionFactorySecondary());
  20. }
  21. }

说明与注意:

  1. 配置类上使用@MapperScan注解来指定当前数据源下定义的Entity和Mapper的包路径;另外需要指定sqlSessionFactorysqlSessionTemplate,这两个具体实现在该配置类中类中初始化。
  2. 配置类的构造函数中,通过@Qualifier注解来指定具体要用哪个数据源,其名字对应在DataSourceConfiguration配置类中的数据源定义的函数名。
  3. 配置类中定义SqlSessionFactorySqlSessionTemplate的实现,注意具体使用的数据源正确(如果使用这里的演示代码,只要第二步没问题就不需要修改)。

根据上面Primary数据源的定义,在com.didispace.chapter39.p包下,定义Primary数据源要用的实体和数据访问对象,比如下面这样:

  1. @Data
  2. @NoArgsConstructor
  3. public class UserPrimary {
  4. private Long id;
  5. private String name;
  6. private Integer age;
  7. public UserPrimary(String name, Integer age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. }
  12. public interface UserMapperPrimary {
  13. @Select("SELECT * FROM USER WHERE NAME = #{name}")
  14. UserPrimary findByName(@Param("name") String name);
  15. @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
  16. int insert(@Param("name") String name, @Param("age") Integer age);
  17. @Delete("DELETE FROM USER")
  18. int deleteAll();
  19. }

根据上面Secondary数据源的定义,在com.didispace.chapter39.s包下,定义Secondary数据源要用的实体和数据访问对象,比如下面这样:

  1. @Data
  2. @NoArgsConstructor
  3. public class UserSecondary {
  4. private Long id;
  5. private String name;
  6. private Integer age;
  7. public UserSecondary(String name, Integer age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. }
  12. public interface UserMapperSecondary {
  13. @Select("SELECT * FROM USER WHERE NAME = #{name}")
  14. UserSecondary findByName(@Param("name") String name);
  15. @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
  16. int insert(@Param("name") String name, @Param("age") Integer age);
  17. @Delete("DELETE FROM USER")
  18. int deleteAll();
  19. }

测试验证

完成了上面之后,就可以写个测试类来尝试一下上面的多数据源配置是否正确了,先来设计一下验证思路:

  1. 往Primary数据源插入一条数据
  2. 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
  3. 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
  4. 往Secondary数据源插入一条数据
  5. 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
  6. 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到

具体实现如下:

  1. @Slf4j
  2. @RunWith(SpringRunner.class)
  3. @SpringBootTest
  4. @Transactional
  5. public class Chapter39ApplicationTests {
  6. @Autowired
  7. private UserMapperPrimary userMapperPrimary;
  8. @Autowired
  9. private UserMapperSecondary userMapperSecondary;
  10. @Before
  11. public void setUp() {
  12. // 清空测试表,保证每次结果一样
  13. userMapperPrimary.deleteAll();
  14. userMapperSecondary.deleteAll();
  15. }
  16. @Test
  17. public void test() throws Exception {
  18. // 往Primary数据源插入一条数据
  19. userMapperPrimary.insert("AAA", 20);
  20. // 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
  21. UserPrimary userPrimary = userMapperPrimary.findByName("AAA");
  22. Assert.assertEquals(20, userPrimary.getAge().intValue());
  23. // 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
  24. UserSecondary userSecondary = userMapperSecondary.findByName("AAA");
  25. Assert.assertNull(userSecondary);
  26. // 往Secondary数据源插入一条数据
  27. userMapperSecondary.insert("BBB", 20);
  28. // 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
  29. userPrimary = userMapperPrimary.findByName("BBB");
  30. Assert.assertNull(userPrimary);
  31. // 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到
  32. userSecondary = userMapperSecondary.findByName("BBB");
  33. Assert.assertEquals(20, userSecondary.getAge().intValue());
  34. }
  35. }
以太坊cppgolang区别 编程

以太坊cppgolang区别

以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
progolang 编程

progolang

Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
golangn个发送者 编程

golangn个发送者

Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
golang技能图谱 编程

golang技能图谱

从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
评论:0   参与:  9