Springcloud+Mybatis使用多数据源的四种方式(小结)

当我们使用SpringCloud和Mybatis时,有时需要使用多数据源来访问不同的数据库。下面介绍四种实现方式。

方式一:使用Mybatis-Plus

Mybatis-Plus 是一个 MyBatis 的增强工具,提供了许多方便的功能,其中就包括多数据源的支持。

  1. 引入 mybatis-plus-boot-starter 依赖

xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>

需要设置 mybatis-plus.mapper-locations 属性,指定 mapper 文件的位置:

properties
mybatis-plus.mapper-locations=classpath:/mapper/**/*Mapper.xml

  1. 配置多数据源

application.yml

yaml
spring:
datasource:
dynamic:
primary: master
datasource:
master:
url: jdbc:mysql://localhost:3306/master?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/slave?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver

  1. 使用注解配置数据源和事务

```java
@Service
public class UserServiceImpl implements UserService {

   @Autowired
   private UserMapper userMapper;

   @Override
   @DataSource("master")
   @Transactional(rollbackFor = Exception.class)
   public void addUser(User user) {
       userMapper.insert(user);
   }

   @Override
   @DataSource("slave")
   public List<User> findAllUsers() {
       return userMapper.selectList(null);
   }

}
```

@DataSource 是自定义注解,用来指定数据源,实现如下:

java
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value() default "master";
}

方式二:使用 aop 和 ThreadLocal 实现多数据源

  1. 创建数据源配置类,动态获取数据源

```java
public class DynamicDataSource extends AbstractRoutingDataSource {

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

}
```

  1. 创建数据源上下文类,存储当前线程的数据源 key

```java
public class DynamicDataSourceContextHolder {

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

   public static void setDataSourceKey(String dataSourceKey) {
       contextHolder.set(dataSourceKey);
   }

   public static String getDataSourceKey() {
       return contextHolder.get();
   }

   public static void clearDataSourceKey() {
       contextHolder.remove();
   }

}
```

  1. 在切面中拦截指定方法,根据方法名称判断数据源

```java
@Slf4j
@Aspect
@Component
public class DataSourceAspect {

   @Pointcut("execution(* com.example.demo.service.*.*(..))")
   private void serviceAspect() {
   }

   @Before("serviceAspect()")
   public void before(JoinPoint joinPoint) {
       String methodName = joinPoint.getSignature().getName();
       if (methodName.startsWith("get")) {
            DynamicDataSourceContextHolder.setDataSourceKey("slave");
       } else {
            DynamicDataSourceContextHolder.setDataSourceKey("master");
       }
       log.info("data source switch to [{}]", DynamicDataSourceContextHolder.getDataSourceKey());
   }

   @After("serviceAspect()")
   public void after() {
       DynamicDataSourceContextHolder.clearDataSourceKey();
       log.info("data source cleared");
   }

}
```

方式三:使用 JdbcTemplate

  1. 在配置文件中定义数据源

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

  1. 在代码中使用 JdbcTemplate 访问数据

```java
@Service
public class UserServiceImpl implements UserService {

   @Autowired
   @Qualifier("masterJdbcTemplate")
   private JdbcTemplate masterJdbcTemplate;

   @Autowired
   @Qualifier("slaveJdbcTemplate")
   private JdbcTemplate slaveJdbcTemplate;

   @Override
   public void addUser(User user) {
       masterJdbcTemplate.update("INSERT INTO user(id, name) VALUES (?,?)", user.getId(), user.getName());
   }

   @Override
   public List<User> findAllUsers() {
       return slaveJdbcTemplate.query("SELECT * FROM user", new BeanPropertyRowMapper<>(User.class));
   }

}
```

DataSource 的配置类:

```java
@Configuration
public class DataSourceConfig {

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

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

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

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

}
```

方式四:使用 SqlSessionFactory

  1. 在配置文件中定义数据源

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

  1. 创建数据源工厂

```java
@Configuration
public class DataSourceConfig {

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

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

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

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

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

   @Bean(name = "masterTransactionManager")
   @Primary
   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);
   }

}
```

  1. 在代码中指定数据源

```java
@Service
public class UserServiceImpl implements UserService {

   @Autowired
   @Qualifier("masterSqlSessionFactory")
   private SqlSessionFactory masterSqlSessionFactory;

   @Autowired
   @Qualifier("slaveSqlSessionFactory")
   private SqlSessionFactory slaveSqlSessionFactory;

   @Override
   public void addUser(User user) {
       SqlSession sqlSession = SqlSessionUtils.getSqlSession(masterSqlSessionFactory);
       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
       userMapper.insert(user);
       sqlSession.commit();
       SqlSessionUtils.closeSqlSession(sqlSession, masterSqlSessionFactory);
   }

   @Override
   public List<User> findAllUsers() {
       SqlSession sqlSession = SqlSessionUtils.getSqlSession(slaveSqlSessionFactory);
       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
       List<User> users = userMapper.selectAll();
       SqlSessionUtils.closeSqlSession(sqlSession, slaveSqlSessionFactory);
       return users;
   }

}
```

以上就是四种使用 SpringCloud 和 Mybatis 实现多数据源的方法,按照自己的场景选择适合的方法即可。

下面是示例代码:

  1. SpringCloud-Mybatis-Plus
  2. SpringCloud-MultipleDataSource

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springcloud+Mybatis使用多数据源的四种方式(小结) - Python技术站

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

相关文章

  • JavaAPI的使用方法详解

    Java API 的使用方法详解 什么是 Java API Java API(Application Programming Interface,应用程序编程接口)是 Java 开发的核心部分,它为程序员提供了许多系统类和接口,这些类和接口可以用来构建和处理各种 Java 应用程序。 Java API 包括标准库(Java SE)和企业库(Java EE),…

    Java 2023年5月23日
    00
  • JAVA基于SnakeYAML实现解析与序列化YAML

    下面就是“JAVA基于SnakeYAML实现解析与序列化YAML”的完整攻略。 什么是YAML? YAML是一种轻量级的数据交换格式,它特别适合于人类编辑或查看。与JSON、XML等数据格式相比,它更为简洁、易于理解和编写,而且可以支持嵌套的数据结构。 SnakeYAML是什么? SnakeYAML是一个Java库,提供对YAML的解析和生成。通过Snake…

    Java 2023年5月26日
    00
  • Sprint Boot @ExceptionHandler使用方法详解

    @ExceptionHandler是Spring Boot中的一个注解,它用于处理控制器方法中抛出的异常。在使用Spring Boot开发Web应用程序时,@ExceptionHandler是非常重要的。本文将详细介绍@ExceptionHandler的作用和使用方法,并提供两个示例说明。 @ExceptionHandler的作用 @ExceptionHan…

    Java 2023年5月5日
    00
  • Java数据库连接池之c3p0简介_动力节点Java学院整理

    Java数据库连接池之c3p0简介 Java数据库连接池之c3p0简介_动力节点Java学院整理是一篇介绍Java数据库连接池技术的文章,其中以c3p0作为具体实现工具进行详细阐述。本文将对该文进行一些补充说明和总结。 1. 什么是数据库连接池? 数据库连接池是实现高效、可靠、可扩展的数据库访问的一种重要技术。在应用系统中,不同的客户端请求需要访问数据库,每…

    Java 2023年6月1日
    00
  • java二叉树的数据插入算法介绍

    Java二叉树的数据插入算法介绍 二叉树是一种非常重要的数据结构,其具有高效的数据插入、查找、删除等特性。本文将介绍Java中二叉树的数据插入算法,希望能为Java开发者提供一些帮助。 什么是二叉树 二叉树是一种树形结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。如果某个节点没有子节点,则称其为叶子节点。二叉树的每个节点都存储了一个关键字和一…

    Java 2023年5月26日
    00
  • Java Mybatis框架Dao层的实现与映射文件以及核心配置文件详解分析

    Java Mybatis是一个优秀的持久层框架,它结合了Java和SQL,解决了面向对象编程中关系数据库的持久化问题。在Java Mybatis中,Dao层是一个非常重要的组成部分,它是应用程序和数据库之间的中间层,主要用于数据访问的封装和管理,而映射文件则用于将SQL语句与Dao层的方法进行映射,核心配置文件则用于对Java Mybatis框架进行配置和管…

    Java 2023年5月20日
    00
  • SpringBoot Starter依赖原理与实例详解

    SpringBoot Starter依赖原理与实例详解 在SpringBoot中,我们可以使用Starter依赖来简化项目的依赖管理。本文将详细讲解SpringBoot Starter依赖原理与实例详解的完整攻略,并提供两个示例。 1. Starter依赖原理 在SpringBoot中,Starter依赖是一种特殊的依赖,它可以自动配置SpringBoot应…

    Java 2023年5月15日
    00
  • SpringMVC中的http Caching的具体使用

    在Web开发中,HTTP缓存是提高网站性能的重要手段之一。Spring MVC提供了多种方式来控制HTTP缓存,本文将详细讲解Spring MVC中的HTTP缓存的具体使用,并提供两个示例说明。 控制HTTP缓存 在Spring MVC中,我们可以使用@Cacheable注解来控制HTTP缓存。下面是一个示例: @GetMapping("/user…

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