SpringBoot整合Mybatis-plus和多数据源配置

目前,业界常用的spring boot整合多数据源的方案主要有两个,一个是Mapper分包方式,另一个是AOP切片方式。最近发现一个更为好使的方案:负责mybatis-plus的baomidou团队开源了一款动态使用多源数据库的解决方案,只需要引入dynamic-datasource的jar包,在service层或mapper层的类或方法前使用@DS注解,即可完成选择指定数据源。

一、在SpringBoot项目pom文件中引入依赖

在SpringBoot项目pom文件中,引入如下依赖:

    <!-- 常用collection操作 依赖 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.1</version>
    </dependency>

    <!-- mybatis-plus 启动依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.1</version>
    </dependency>

    <!-- datasource多数据源 启动依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>3.1.0</version>
    </dependency>

    <!-- mysql connector 依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- lombok 依赖 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

二、application.properties属性文件增加数据源配置项

# 多数据源配置
#设置默认的数据源或者数据源组, 默认值即为 master
spring.datasource.dynamic.primary=master
#设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时会抛出异常,不启动会使用默认数据源.
spring.datasource.dynamic.strict=false
## 默认数据源 master
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/mysql-plus?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
spring.datasource.dynamic.datasource.master.username=test_user
spring.datasource.dynamic.datasource.master.password=test_pswd
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
## 数据源 slave
spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://localhost:3306/mysql-plus-slave?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
spring.datasource.dynamic.datasource.slave.username=test_user
spring.datasource.dynamic.datasource.slave.password=test_pswd
spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.jdbc.Driver

说明:

1.spring.datasource.dynamic.primary=master 表示设置master数据源为primary数据源。

2.spring.datasource.dynamic.strict=false 设置严格模式,默认false不启动.。若设置为true,则在未匹配到指定数据源时会抛出异常。若设置为false,则在未匹配到指定数据源时会使用默认数据源。

3.测试使用的user表sql为:

DROP TABLE IF EXISTS`user`;
CREATE TABLE `user` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT "自增id",
  `user_name` varchar(255) DEFAULT '' COMMENT "用户名称",
  `age` INTEGER(10) DEFAULT 0 COMMENT "用户年龄",
  `sex` INTEGER(10) DEFAULT 0 COMMENT "性别 0女 1男",
  `school` varchar(255) DEFAULT '' COMMENT "用户学校",
  `type` INTEGER(10) DEFAULT 0 COMMENT "类型 0正常 1马甲",
  `created_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `updated_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '更新时间',
   PRIMARY KEY (`id`),
   KEY `school` (`school`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT="用户记录表";

## default db
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, '王二', 25, 0, '清华',0);
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, '张三', 25,1, '清华',1);
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, '李四', 25,1, '清华',1);

## custom db
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, ''mvp'', 25, 0, '北大',0);
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, ''jack'', 25,1, '北大',1);
INSERT INTO `user`(`id`, `user_name`, `age`, `sex`, `school`, `type`) VALUES (0, ''lily'', 25,1, '北大',1);

三、@DS 注解

  • 作用: 用于切换数据源。

  • 修饰范围: 在方法上或类上。当同时存在于方法和类上时,方法注解优先(局部优先)。

  • 属性: value值为切换数据源名称。

如果在类或方法上没有使用@DS注解,那么会使用默认primary首选库。

四、Mapper层代码开发示例

mapper层代码示例为:

@Mapper
@Repository
public interface UserDao extends BaseMapper<UserPo> {

    @Select("select * from `user` where sex = #{sex, jdbcType=INTEGER} limit 10")
    List<UserPo> getByTypeDefaultDB(@Param("sex") Integer sex);

    @Select("select * from `user` where sex = #{sex, jdbcType=INTEGER} limit 10")
    @DS("slave")
    List<UserPo> getByTypeCustomDB(@Param("sex") Integer sex);
}

五、Service层代码开发示例

service层代码开发示例如下所示。

service接口示例为:

public interface UserService extends IService<UserPo> {

    List<UserPo> selectFromDefaultDB();

    List<UserPo> selectFromCustomDB();

    public List<UserPo> queryFromDefaultDB();
    
    public List<UserPo> queryFromCustomDB();
}

service层接口的具体实现类的示例为:

@Service
public class UserServiceImpl extends ServiceImpl<UserDao, UserPo> implements UserService {

    @Resource
    private UserDao userDao;

    @Override
    public List<UserPo> selectFromDefaultDB() {
        QueryWrapper<UserPo> wrapper = Wrappers.query();
        wrapper.eq("sex", 1);
        wrapper.last("limit 10");
        return userDao.selectList(wrapper);
    }

    @Override
    @DS("slave")
    public List<UserPo> selectFromCustomDB() {
        QueryWrapper<UserPo> wrapper = Wrappers.query();
        wrapper.eq("sex", 1);
        wrapper.last("limit 10");
        return userDao.selectList(wrapper);
    }

    @Override
    public List<UserPo> queryFromDefaultDB() {
        QueryWrapper<UserPo> wrapper = Wrappers.query();
        wrapper.eq("sex", 1);
        wrapper.last("limit 10");
        return this.list(wrapper);
    }

    @Override
    @DS("slave")
    public List<UserPo> queryFromCustomDB() {
        QueryWrapper<UserPo> wrapper = Wrappers.query();
        wrapper.eq("sex", 1);
        wrapper.last("limit 10");
        return this.list(wrapper);
    }
}

注意:@DS注解用在service实现类或其方法中,其value值为配置文件中spring.datasource.dynamic.datasource.xxx后的xxx值。

六、测试代码示例

测试代码示例,如下所示:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Resource
    private UserService userService;

    @Test
    public void selectSomeTest() {
        System.out.println("From default DB:");
        List<UserPo> userPos = userService.selectFromDefaultDB();
        if (CollectionUtils.isNotEmpty(userPos)) {
            userPos.forEach(user -> System.out.println("user: " + user));
        } else  {
            System.out.println("userPos is empty");
        }

        System.out.println("From slave DB:");
        userPos = userService.selectFromCustomDB();
        if (CollectionUtils.isNotEmpty(userPos)) {
            userPos.forEach(user -> System.out.println("user: " + user));
        } else  {
            System.out.println("userPos is empty");
        }
    }

    @Test
    public void queryFromDBTest() {
        List<UserPo> userPos = userService.queryFromDefaultDB();
        System.out.println("From default DB:");
        if (CollectionUtils.isNotEmpty(userPos)) {
            userPos.forEach(user -> System.out.println("user: " + user));
        } else  {
            System.out.println("userPos is empty");
        }

        System.out.println("From slave DB:");
        userPos = userService.queryFromCustomDB();
        if (CollectionUtils.isNotEmpty(userPos)) {
            userPos.forEach(user -> System.out.println("user: " + user));
        } else  {
            System.out.println("userPos is empty");
        }
    }
}

经验证,测试用例符合预期。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值