DS注解作用

文章讲述了MyBatis-Plus框架中的@DS注解如何在多租户系统中动态切换数据源,以及与SpringBoot和AOP的集成,同时提到了在使用@DS和@Transactional注解时可能出现的覆盖问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@DS(“#header.dbTenantId”) 是 MyBatis-Plus 框架中的注解,用于指定数据源。其中 #header.dbTenantId 表示从请求头中获取 dbTenantId 参数的值,作为数据源的标识。
@DS(“#tenantId”)中的 #tenantId 表示从方法参数中获取 tenantId 参数的值,作为数据源的标识。
@DS(“master”) 中的 “master” 表示数据源的标识,即指定使用名为 master 的数据源。
在多租户系统中,不同的租户可能需要连接不同的数据库,因此需要动态切换数据源。使用 @DS 注解可以方便地实现动态切换数据源的功能。通过在注解中指定数据源的标识,可以让 MyBatis-Plus 框架自动切换到对应的数据源,从而实现动态切换数据源的功能。
需要注意的是,使用 @DS 注解需要在 Spring Boot 配置文件中配置多个数据源,并在注解中指定数据源的标识。同时,也需要在代码中使用 @Mapper 注解标注 Mapper 接口,以便 MyBatis-Plus 框架能够自动扫描并生成对应的 Mapper 实现类。

样例:

spring:
  datasource:
    tenant1:
      url: jdbc:mysql://localhost:3306/tenant1_db?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver
    tenant2:
      url: jdbc:mysql://localhost:3306/tenant2_db?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

在上面的配置文件中,定义了两个数据源,分别为 tenant1 和 tenant2。其中,tenant1 数据源连接的是 tenant1_db 数据库,tenant2 数据源连接的是 tenant2_db 数据库。
在代码中,可以使用 @DS 注解动态指定使用哪个租户的数据源。例如:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @DS("#tenantId")
    @Override
    public List<User> listUsers(Long tenantId) {
        return userMapper.selectList(null);
    }
}

失效情况:
updateUser方法的数据源会覆盖掉getUserById方法的数据源
可以将getUserById方法放到另一个类中,使之代理注解生效

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("dataSource1")
    private DataSource dataSource1;

    @Autowired
    @Qualifier("dataSource2")
    private DataSource dataSource2;

    @Override
    @DS("dataSource1")
    @Transactional(value = "transactionManager1")
    public User getUserById(int id) {
        // 使用dataSource1查询用户信息
        // ...
    }

    @Override
    @Transactional(value = "transactionManager2")
    @DS("dataSource2")
    public void updateUser(User user) {
        // 在这里调用getUserById方法,应该使用dataSource1数据源
        User oldUser = getUserById(user.getId());

        // 使用dataSource2更新用户信息
        // ...
    }
}

原因:

@DS注解是通过AOP实现的,它会在方法执行前切换数据源。而@Transactional注解也是通过AOP实现的,它会在方法执行前开启事务,并在方法执行后提交或回滚事务。
当一个方法同时被@DS和@Transactional注解修饰时,Spring会先创建一个代理对象,这个代理对象会同时包含@DS和@Transactional的功能。当代理对象调用这个方法时,它会先切换数据源,然后开启事务。在事务执行期间,如果这个方法调用了另一个方法,那么这个方法也会被代理对象所代理,也就是说,这个方法也会被切换到当前数据源,并且也会被包含在当前事务中。
如果在调用另一个方法时,这个方法上也有@DS注解,那么这个注解会被代理对象所覆盖,也就是说,这个方法会使用当前数据源,而不是它本来应该使用的数据源。这就是为什么@DS注解会被覆盖的原因。

### DS 注解使用说明 `@DS` 注解主要用于多数据源切换,在不同的业务逻辑中动态指定要使用的数据源。此注解通常应用于方法级别或类级别,以便在整个类中的所有方法或特定的方法调用期间更改默认的数据源[^2]。 当应用程序中有多个数据源配置时,可以通过 `@DS` 注解来指明具体的操作应该作用于哪个数据源上。需要注意的是,并不是所有的环境中都支持该注解;对于一些特殊的环境或者非 Spring 管理的 Bean 来说,可能会遇到不兼容的情况,这时就需要采取其他方式实现类似的功能。 #### 示例代码展示 下面是一个简单的例子,展示了如何在一个基于 Spring 的应用里利用 `@DS` 注解来进行不同数据库之间的切换: ```java import com.baomidou.dynamic.datasource.annotation.DS; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @Service public class MultiDataSourceService { @Autowired private JdbcTemplate jdbcTemplate; // 切换到名为 'ds1' 的数据源执行查询操作 @DS("ds1") public List<Map<String, Object>> queryFromDs1() { String sql = "SELECT * FROM table_in_ds1"; return jdbcTemplate.queryForList(sql); } // 切换回默认数据源或其他已定义的数据源 'ds2' @DS("ds2") public int insertIntoDs2(Map<String, Object> params) { String sql = "INSERT INTO table_in_ds2 (col1, col2) VALUES (:val1, :val2)"; return jdbcTemplate.update(sql, params); } } ``` 在这个例子中,服务层的方法被标记上了 `@DS` 注解,从而可以在运行时改变当前线程所关联的数据源连接池。这使得开发者能够灵活地控制各个请求对应的具体数据库实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhou22-codeWalker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值