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",
    <<<<<<< HEAD
        sqlSessionFactoryRef = "sqlSessionFactorySecondary",
        sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
    =======
        sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
        sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
    

origin/hp
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数据源要用的实体和数据访问对象,比如下面这样:

```java
@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());
        }
    
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容