Springbooot的多数据源配置

JdbcTemplate

依赖配置

  • 依赖如下

    <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>
    </dependencies>
    

添加多数据源的配置

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

    spring.datasource.primary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test1
    spring.datasource.primary.username=test
    spring.datasource.primary.password=123456
    spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
    # 次数据源
    spring.datasource.secondary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test2
    spring.datasource.secondary.username=test
    spring.datasource.secondary.password=123456
    spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
    
  • 说明与注意

    1. 多数据源配置的时候,与单数据源不同点在于spring.datasource之后多设置一个数据源名称primarysecondary来区分不同的数据源配置,这个前缀将在后续初始化数据源的时候用到。
    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.,那么就是这个配置项的问题。

初始化数据源和JdbcTemplate

  • 完成多数据源的配置信息之后,就来创建个配置类来加载这些配置信息,初始化数据源,以及初始化每个数据源要用的JdbcTemplate。你只需要在你的Spring Boot应用下添加下面的这个配置类即可完成!

    package tk.fulsun.demo.config;
    
    import javax.sql.DataSource;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.core.JdbcTemplate;
    
    /**
     * @author fsun7
     * @description: 数据源的配置信息
     * @date 6/11/2021 3:20 PM
     */
    @Configuration
    public class DataSourceConfiguration {
      @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();
      }
    
      @Bean
      public JdbcTemplate primaryJdbcTemplate(
          @Qualifier("primaryDataSource") DataSource primaryDataSource) {
        return new JdbcTemplate(primaryDataSource);
      }
    
      @Bean
      public JdbcTemplate secondaryJdbcTemplate(
          @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        return new JdbcTemplate(secondaryDataSource);
      }
    }
    
  • 说明与注意

    1. 前两个Bean是数据源的创建,通过@ConfigurationProperties可以知道这两个数据源分别加载了spring.datasource.primary.*spring.datasource.secondary.*的配置。
    2. @Primary注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean
    3. 后两个Bean是每个数据源对应的JdbcTemplate。可以看到这两个JdbcTemplate创建的时候,分别注入了primaryDataSource数据源和secondaryDataSource数据源

测试

  • 完成了上面之后,我们就可以写个测试类来尝试一下上面的多数据源配置是否正确了,比如下面这样:

    package tk.fulsun.demo;
    
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.jupiter.api.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * @author fsun7
     * @description: 主测试类
     * @date 6/11/2021 3:25 PM
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest
    class ApplicationTest {
    
        @Autowired protected JdbcTemplate primaryJdbcTemplate;
    
        @Autowired protected JdbcTemplate secondaryJdbcTemplate;
    
        @Before
        public void setUp() {
            primaryJdbcTemplate.update("DELETE  FROM  user ");
            secondaryJdbcTemplate.update("DELETE  FROM  user ");
        }
    
        @Test
        public void test() throws Exception {
            // 往第一个数据源中插入 2 条数据
            primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);
            primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);
    
            // 往第二个数据源中插入 1 条数据,若插入的是第一个数据源,则会主键冲突报错
            secondaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);
    
            // 查一下第一个数据源中是否有 2 条数据,验证插入是否成功
            Assert.assertEquals(
                "2", primaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
    
            // 查一下第一个数据源中是否有 1 条数据,验证插入是否成功
            Assert.assertEquals(
                "1", secondaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
        }
    }
    
    
  • 查询数据库

    mysql> select * from test1.user;
    +------+------+
    | name | age  |
    +------+------+
    | aaa  |   20 |
    | bbb  |   30 |
    +------+------+
    2 rows in set (0.00 sec)
    
    mysql> select * from test2.user;
    +------+------+
    | name | age  |
    +------+------+
    | ccc  |   20 |
    +------+------+
    1 row in set (0.00 sec)
    
    

    说明

    • 有两个JdbcTemplate,为什么不用@Qualifier指定?
      • 这里顺带说个小知识点,当我们不指定的时候,会采用参数的名字来查找Bean,存在的话就注入。
    • 这两个JdbcTemplate创建的时候,我们也没指定名字,它们是如何匹配上的?
      • 这里也是一个小知识点,当我们创建Bean的时候,默认会使用方法名称来作为Bean的名称,所以这里就对应上了。

Spring Data JPA

依赖配置

  • 添加jpa的依赖

    <!--    <dependency>-->
    <!--      <groupId>org.springframework.boot</groupId>-->
    <!--      <artifactId>spring-boot-starter-jdbc</artifactId>-->
    <!--    </dependency>-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    

添加多数据源的配置

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

    spring.datasource.primary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test1
    spring.datasource.primary.username=test
    spring.datasource.primary.password=123456
    spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
    # 次数据源
    spring.datasource.secondary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test2
    spring.datasource.secondary.username=test
    spring.datasource.secondary.password=123456
    spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
    # 日志打印执行的SQL
    spring.jpa.show-sql=true
    # Hibernate的DDL策略
    spring.jpa.hibernate.ddl-auto=create-drop
    
  • 这里除了JPA自身相关的配置之外,与JdbcTemplate配置时候的数据源配置完全是一致的

初始化数据源与JPA配置

  • 完成多数据源的配置信息之后,就来创建个配置类来加载这些配置信息,初始化数据源,以及初始化每个数据源要用的JPA配置。

  • 由于JPA的配置要比JdbcTemplate的复杂很多,所以我们可将配置拆分一下来处理

  • 在使用JPA的时候,需要为不同的数据源创建不同的package来存放对应的Entity和Repository,以便于配置类的分区扫描

    • 类名上的注解@EnableJpaRepositories中指定Repository的所在位置
    • LocalContainerEntityManagerFactoryBean创建的时候,指定Entity所在的位置
    • 其他主要注意在互相注入时候,不同数据源不同配置的命名,基本就没有什么大问题了
配置DataSource类
  • 单独建一个多数据源的配置类,比如下面这样:

    import javax.sql.DataSource;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Primary;
    
    /**
     * @author fsun7
     * @description: JPA数据源的配置类
     * @date 6/11/2021 4:08 PM
     */
    @Configuration
    public class JpaDataSourceConfiguration {
      @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();
      }
    }
    
    
  • 可以看到内容跟JdbcTemplate时候是一模一样的。通过@ConfigurationProperties可以知道这两个数据源分别加载了spring.datasource.primary.*spring.datasource.secondary.*的配置。

  • @Primary注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean真正差异部分在下面的JPA配置上。

JPA配置
  • 分别创建两个数据源的JPA配置。

  • primary数据源的JPA配置:

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",
        transactionManagerRef = "transactionManagerPrimary",
        basePackages = {"tk.fulsun.demo.entity"}) // 设置Repository所在位置
    class PrimaryConfig {
    
      @Autowired
      @Qualifier("primaryDataSource")
      private DataSource primaryDataSource;
    
      @Autowired private JpaProperties jpaProperties;
      @Autowired private 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) {
        return builder
            .dataSource(primaryDataSource)
            .packages("tk.fulsun.demo.entity") // 设置实体类所在位置
            .persistenceUnit("primaryPersistenceUnit")
            .properties(getVendorProperties())
            .build();
      }
    
      @Primary
      @Bean(name = "transactionManagerPrimary")
      public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
      }
    }
    
  • Secondary数据源的JPA配置:

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySecondary",
        transactionManagerRef="transactionManagerSecondary",
        basePackages= { "com.didispace.chapter38.s" }) //设置Repository所在位置
    class SecondaryConfig {
    
        @Autowired
        @Qualifier("secondaryDataSource")
        private DataSource secondaryDataSource;
    
        @Autowired
        private JpaProperties jpaProperties;
        @Autowired
        private 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.didispace.chapter38.s") //设置实体类所在位置
                .persistenceUnit("secondaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
        }
    
        @Bean(name = "transactionManagerSecondary")
        PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
        }
    
    }
    

Repository编写

  • 编写实体类

    package tk.fulsun.demo.dao.p;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @author fsun7
     * @description: TODO
     * @date 6/11/2021 4:25 PM
     */
    @Entity
    @Data
    @NoArgsConstructor
    public class User {
      @Id @GeneratedValue private Long id;
    
      private String name;
      private Integer age;
    
      public User(String name, Integer age) {
        this.name = name;
        this.age = age;
      }
    }
    
  • Repository

    package tk.fulsun.demo.dao.p;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * @author fsun7
     * @description: UserRepository
     * @date 6/11/2021 4:26 PM
     */
    public interface UserRepository extends JpaRepository<User, Long> {}
    
    
  • secondary数据库的表
  package tk.fulsun.demo.dao.s;
  
  import javax.persistence.Entity;
  import javax.persistence.GeneratedValue;
  import javax.persistence.Id;
  import lombok.Data;
  import lombok.NoArgsConstructor;
  
  /**
   * @author fsun7
   * @description: Message
   * @date 6/11/2021 4:27 PM
   */
  @Entity
  @Data
  @NoArgsConstructor
  public class Message {
  
    @Id @GeneratedValue private Long id;
  
    private String title;
    private String message;
  
    public Message(String title, String message) {
      this.title = title;
      this.message = message;
    }
  }
  
  
  package tk.fulsun.demo.dao.s;
  
  import org.springframework.data.jpa.repository.JpaRepository;
  
  /**
   * @author fsun7
   * @description: MessageRepository
   * @date 6/11/2021 4:28 PM
   */
  public interface MessageRepository extends JpaRepository<Message, Long> {}
  

测试

  • 测试通过不同的Repository往不同的数据源插入数据,然后查询一下总数是否是对的

    package tk.fulsun.demo;
    
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.jupiter.api.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import tk.fulsun.demo.dao.p.User;
    import tk.fulsun.demo.dao.p.UserRepository;
    import tk.fulsun.demo.dao.s.Message;
    import tk.fulsun.demo.dao.s.MessageRepository;
    
    /**
     * @author fsun7
     * @description: JPA方式多数据源测试
     * @date 6/11/2021 4:23 PM
     */
    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JPAApplicationTests {
      @Autowired private UserRepository userRepository;
      @Autowired private MessageRepository messageRepository;
    
      @Test
      public 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

依赖配置

  • 移除jpa的依赖

    <!--    <dependency>-->
    <!--      <groupId>org.springframework.boot</groupId>-->
    <!--      <artifactId>spring-boot-starter-jdbc</artifactId>-->
    <!--    </dependency>-->
    <!--    <dependency>-->
    <!--      <groupId>org.springframework.boot</groupId>-->
    <!--      <artifactId>spring-boot-starter-data-jpa</artifactId>-->
    <!--    </dependency>-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.4</version>
    </dependency>
    

添加多数据源的配置

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

    spring.datasource.primary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test1
    spring.datasource.primary.username=test
    spring.datasource.primary.password=123456
    spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
    # 次数据源
    spring.datasource.secondary.jdbc-url=jdbc:mysql://192.168.56.101:3306/test2
    spring.datasource.secondary.username=test
    spring.datasource.secondary.password=123456
    spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
    
    # 日志打印执行的SQL
    #spring.jpa.show-sql=true
    # Hibernate的DDL策略
    #spring.jpa.hibernate.ddl-auto=update
    

初始化数据源与MyBatis配置

  • 完成多数据源的配置信息之后,就来创建个配置类来加载这些配置信息,初始化数据源,以及初始化每个数据源要用的MyBatis配置。

  • 这里我们继续将数据源与框架配置做拆分处理:

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

    package tk.fulsun.demo.mybatis.config;
    
    import javax.sql.DataSource;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    
    /**
     * @author fsun7
     * @description: 数据源配置
     * @date 6/11/2021 4:49 PM
     */
    @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();
      }
    }
    
    
  • 可以看到内容跟JdbcTemplate、Spring Data JPA的时候是一模一样的。通过@ConfigurationProperties可以知道这两个数据源分别加载了spring.datasource.primary.*spring.datasource.secondary.*的配置。

  • @Primary注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean真正差异部分在下面的JPA配置上。

MyBatis配置
  • 分别创建两个数据源的MyBatis配置。

  • Primary数据源的JPA配置:

    package tk.fulsun.demo.mybatis.config;
    
    import javax.sql.DataSource;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author fsun7
     * @description: MyBatis配置
     * @date 6/11/2021 4:50 PM
     */
    @Configuration
    @MapperScan(
        basePackages = "tk.fulsun.demo.mybatis.mapper.p",
        sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
        sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
    public class PrimaryConfig {
      private DataSource primaryDataSource;
    
      public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
        this.primaryDataSource = primaryDataSource;
      }
    
      @Bean
      public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(primaryDataSource);
        return bean.getObject();
      }
    
      @Bean
      public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryPrimary());
      }
    }
    
    
  • Secondary数据源的JPA配置:

    package tk.fulsun.demo.mybatis.config;
    
    import javax.sql.DataSource;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author fsun7
     * @description: MyBatis配置
     * @date 6/11/2021 4:50 PM
     */
    @Configuration
    @MapperScan(
        basePackages = "tk.fulsun.demo.mybatis.mapper.s",
        sqlSessionFactoryRef = "sqlSessionFactorySecondary",
        sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
    
    public class SecondaryConfig {
      private DataSource secondaryDataSource;
    
      public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        this.secondaryDataSource = secondaryDataSource;
      }
        
      @Bean
      public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(secondaryDataSource);
        return bean.getObject();
      }
        
      @Bean
      public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactorySecondary());
      }
    }
    
    
说明与注意
  1. 配置类上使用@MapperScan注解来指定当前数据源下定义的Entity和Mapper的包路径;另外需要指定sqlSessionFactory和sqlSessionTemplate,这两个具体实现在该配置类中类中初始化。
  2. 配置类的构造函数中,通过@Qualifier注解来指定具体要用哪个数据源,其名字对应在DataSourceConfiguration配置类中的数据源定义的函数名。
  3. 配置类中定义SqlSessionFactory和SqlSessionTemplate的实现,注意具体使用的数据源正确(

Mapper层编写

  • 根据上面Primary数据源的定义,在tk.fulsun.demo.mybatis.mapper.p包下,定义Primary数据源要用的实体和数据访问对象,比如下面这样:

    @Data
    @NoArgsConstructor
    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 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();
    
    }
    
  • 根据上面Secondary数据源的定义,在tk.fulsun.demo.mybatis.mapper.s包下,定义Secondary数据源要用的实体和数据访问对象,比如下面这样:

    @Data
    @NoArgsConstructor
    public class UserSecondary {
    
        private Long id;
    
        private String name;
        private Integer age;
    
        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();
    }
    

测试验证

  • 完成了上面之后,我们就可以写个测试类来尝试一下上面的多数据源配置是否正确了,先来设计一下验证思路:
  1. 往Primary数据源插入一条数据
  2. 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
  3. 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
  4. 往Secondary数据源插入一条数据
  5. 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
  6. 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到
  • 具体实现如下:

    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Transactional
    public class Chapter39ApplicationTests {
    
        @Autowired
        private UserMapperPrimary userMapperPrimary;
        @Autowired
        private UserMapperSecondary userMapperSecondary;
    
        @Before
        public void setUp() {
            // 清空测试表,保证每次结果一样
            userMapperPrimary.deleteAll();
            userMapperSecondary.deleteAll();
        }
    
        @Test
        public void test() throws Exception {
            // 往Primary数据源插入一条数据
            userMapperPrimary.insert("AAA", 20);
    
            // 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
            UserPrimary userPrimary = userMapperPrimary.findByName("AAA");
            Assert.assertEquals(20, userPrimary.getAge().intValue());
    
            // 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
            UserSecondary userSecondary = userMapperSecondary.findByName("AAA");
            Assert.assertNull(userSecondary);
    
            // 往Secondary数据源插入一条数据
            userMapperSecondary.insert("BBB", 20);
    
            // 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
            userPrimary = userMapperPrimary.findByName("BBB");
            Assert.assertNull(userPrimary);
    
            // 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到
            userSecondary = userMapperSecondary.findByName("BBB");
            Assert.assertEquals(20, userSecondary.getAge().intValue());
        }
    
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值