tk-mybatis整合springBoot使用两个数据源的方法

下面是“tk-mybatis整合springBoot使用两个数据源的方法”的完整攻略及两条示例:

一、准备工作

在进行整合之前,我们需要做以下准备工作:

  1. 创建两个数据库,分别为db1db2,并分别创建表user,表结构如下:
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
  1. pom.xml中添加tk-mybatisdruidmysql-connector-java依赖:
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.9</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.22</version>
</dependency>

二、配置数据源

application.yml中配置数据源,如下:

spring:
  datasource:
    master:
      url: jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      url: jdbc:mysql://localhost:3306/db2?useSSL=false&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

### druid连接池配置
  druid:
    master:
      maxActive: 32
      initialSize: 2
      minIdle: 2
      maxWait: 60000
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 20
      validationQuery: select 1 from dual
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      filters: stat
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    slave:
      maxActive: 32
      initialSize: 2
      minIdle: 2
      maxWait: 60000
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 20
      validationQuery: select 1 from dual
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      filters: stat
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

上面的配置中,我们使用了两个数据源,分别为masterslave,并分别对应db1db2两个数据库。其中,我们使用了druid连接池来管理数据源,提高应用的性能。

三、整合tk-mybatis

application.yml中配置tk-mybatis,如下:

tk:
  mybatis:
    mapper-locations: classpath:mapper/**Mapper.xml
    config-location: classpath:mybatis-config.xml
    check-config-location: true
    mapper-ids: com.example.mapper.*
    sqlSessionTemplate:
      masters: masterSqlSessionTemplate
      slaves: slaveSqlSessionTemplate

com.example.config包中创建DataSourceConfig类,如下:

@Configuration
@Slf4j
public class DataSourceConfig {

    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                               @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put("master", masterDataSource);
        targetDataSources.put("slave", slaveDataSource);
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        return dynamicDataSource;
    }

    @Bean(name = "masterTransactionManager")
    public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "slaveTransactionManager")
    public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "masterSqlSessionFactory")
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/master/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "slaveSqlSessionFactory")
    public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/slave/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "masterSqlSessionTemplate")
    public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "slaveSqlSessionTemplate")
    public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

com.example.config包中创建DynamicDataSource类,实现动态数据源切换,代码如下:

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSource();
    }

}

com.example.config包中创建DynamicDataSourceContextHolder类,定义数据源的上下文,代码如下:

public class DynamicDataSourceContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    /**
     * 设置数据源名
     *
     * @param dataSource 数据源名
     */
    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    /**
     * 获取数据源名
     *
     * @return 数据源名
     */
    public static String getDataSource() {
        return contextHolder.get();
    }

    /**
     * 清除数据源名
     */
    public static void clearDataSource() {
        contextHolder.remove();
    }

}

com.example.aop包中创建DataSourceAop类,为数据源切换提供切面支持,代码如下:

@Slf4j
@Aspect
@Component
public class DataSourceAop {

    @Pointcut("@annotation(com.example.annotation.Slave) ")
    public void dsSlavePointcut() {
    }

    @Before("dsSlavePointcut()")
    public void setSlaveDataSource(JoinPoint joinPoint) {
        DynamicDataSourceContextHolder.setDataSource("slave");
    }

    @After("dsSlavePointcut()")
    public void restoreDataSource(JoinPoint joinPoint) {
        DynamicDataSourceContextHolder.clearDataSource();
    }

}

com.example.annotation包中创建Slave注解,用于标注从数据源,代码如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Slave {

}

四、示例

1. 使用主数据源的示例

com.example.mapper.master包中创建UserMapper接口,定义查询方法,如下:

@Mapper
public interface UserMapper {

    List<User> selectAll();

}

com.example.service包中创建UserService类,注入UserMapper,实现查询所有用户的方法,如下:

@Service
public class UserService {

    @Autowired
    UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.selectAll();
    }

}

com.example.controller包中创建UserController类,注入UserService,实现查询所有用户的接口,如下:

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/users")
    public List<User> getUsers() {
        return userService.getAllUsers();
    }

}

启动应用,在浏览器中访问http://localhost:8080/users,可以查看到主数据源中的所有用户。

2. 使用从数据源的示例

com.example.mapper.slave包中创建UserMapper接口,定义查询方法,如下:

@Mapper
public interface UserMapper {

    @Slave
    List<User> selectAll();

}

com.example.service包中创建UserService类,注入UserMapper,实现查询所有用户的方法,如下:

@Service
public class UserService {

    @Autowired
    UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.selectAll();
    }

}

com.example.controller包中创建UserController类,注入UserService,实现查询从数据源所有用户的接口,如下:

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/slave-users")
    public List<User> getSlaveUsers() {
        return userService.getAllUsers();
    }

}

启动应用,在浏览器中访问http://localhost:8080/slave-users,可以查看到从数据源中的所有用户。

到这里,tk-mybatis整合springBoot使用两个数据源的方法就详细讲解完毕了。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:tk-mybatis整合springBoot使用两个数据源的方法 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java dbcp连接池基本使用方法详解

    首先,让我们来介绍一下什么是Java DBCP连接池。 什么是Java DBCP连接池? Java DBCP(Database Connection Pool)连接池是一种连接管理工具,它通过在内存中维护一定数量的数据库连接,避免了重复连接数据库的开销,提升了应用程序的性能。Java DBCP连接池可以在应用程序和数据库服务之间提供一个中间层,负责管理和分配…

    Java 2023年5月19日
    00
  • springboot项目启动慢的问题排查方式

    当Spring Boot项目启动慢或者无法正常启动时,可以采用以下排查方式: 一、查看启动日志输出,分析问题 启动Spring Boot项目时,可以查看控制台输出的启动日志,了解项目启动时的具体情况。如果日志中有异常或者错误信息,可以根据异常信息进行问题排查。 查看日志的方式有两种: 直接查看控制台输出的日志信息。 将日志输出到文件中,可以通过配置日志级别、…

    Java 2023年5月20日
    00
  • JavaWeb Servlet技术及其应用实践

    JavaWeb Servlet技术及其应用实践 什么是Servlet? Servlet是JavaWeb中的一个组件,是JavaWeb中实现业务逻辑的重要方式之一。在JavaWeb中,Servlet让我们可以获取HTTP请求的参数、读写HTTP头信息、返回HTTP响应、写入HTTP头信息等。 Servlet的应用实践 基础应用 我们可以通过以下步骤使用Serv…

    Java 2023年5月20日
    00
  • Java中动态规则的实现方式示例详解

    这篇文章将详细讲解Java中动态规则的实现方式,并且提供两个示例来帮助读者更好地理解此概念。在开始之前,我们来了解一下动态规则的概念。 什么是动态规则 动态规则是指在程序运行时可以动态地修改规则,而无需重新编译代码。这种实现方式增加了程序的灵活性和可维护性,而且不会影响程序的可靠性和性能。 Java中动态规则的实现方式有很多种,下面我们就来看两个示例。 示例…

    Java 2023年5月18日
    00
  • 海量数据去重排序bitmap(位图法)在java中实现的两种方法

    海量数据去重排序bitmap(位图法)是一种高效的数据处理方法,可以有效提升数据处理的效率。在Java中实现海量数据去重排序bitmap(位图法)可以采用以下两种方法: 1. 使用Java BitSet类实现位图法 1.1 初始数据的准备 在使用位图法进行去重排序之前,需要先将原始数据以字符串的形式进行处理,并按照一定规则转化为二进制码。在这个例子中,我们将…

    Java 2023年5月26日
    00
  • Java使用正则表达式进行匹配且对匹配结果逐个替换

    Java中使用正则表达式进行匹配和替换是非常常见的操作,可以用来处理各种文本数据。下面是Java使用正则表达式进行匹配且对匹配结果逐个替换的攻略。 正则表达式基础 在Java中,使用正则表达式的功能主要是通过java.util.regex包提供的类实现的,常用的类包括Pattern和Matcher。在使用之前,我们需要先了解正则表达式的基本语法: .:匹配任…

    Java 2023年5月27日
    00
  • EJB 3.0 开发指南之定时服务

    EJB 3.0 开发指南之定时服务 什么是定时服务? 定时服务是一种可以按照预定时间自动执行的任务服务,可以定时发送邮件、清理垃圾数据等操作。在 Java EE 中,可以使用 EJB(Enterprise JavaBeans)实现定时任务。 实现定时服务的步骤 创建 EJB 在 Java EE 项目中,首先需要创建一个 EJB,这个 EJB 将被用来实现定时…

    Java 2023年6月15日
    00
  • 在JS中如何调用JSP中的变量

    在JS中如何调用JSP中的变量需要用到以下两步: 在JSP中将要调用的变量声明为JS全局变量 在JS中通过调用全局变量来获取JSP中的变量值 下面我们分别来详细讲解。 1. 声明全局变量 在JSP中,我们需要将要被JS调用的变量声明为全局变量。在JSP中,我们可以使用<script>标签来声明全局变量,例如: <% String name …

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部