# db-router-spring-boot-starter
**Repository Path**: iferry/db-router-spring-boot-starter
## Basic Information
- **Project Name**: db-router-spring-boot-starter
- **Description**: 数据库分库分表组件,集成了 mybatis plugin,以spring boot starter的形式提供使用
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 0
- **Created**: 2022-07-14
- **Last Updated**: 2023-05-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 引入说明
## 一、本地安装
1. 克隆项目到本地
2. mvn clean install
## 二、导入依赖
```xml
cn.cscamp.middleware
db-router-spring-boot-starter
1.0-SNAPSHOT
```
## 三、配置文件
application.yaml/application.properties
```yaml
# 多数据源路由配置
mini-db-router:
jdbc:
datasource:
dbCount: 2
tbCount: 4
default: db00
list: db01,db02
db00:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/${database}?useUnicode=true
username: root
password: abc123456
db01:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/${database01}?useUnicode=true
username: root
password: abc123456
db02:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/${database02}?useUnicode=true
username: root
password: abc123456
```
## 四、使用案例
> - 如果一个表只分库不分表,则它的 sql 语句并不会有什么差异
> - 如果需要分表,那么则需要在表名后面加入 user_take_activity_${tbIdx} 同时入参对象需要继承 DBRouterBase 这样才可以拿到 tbIdx 分表信息
### 分库案例
第一步: 在需要使用数据库路由的DAO方法上加入注解
> @DBRouter(key = "uId") key 是入参对象中的属性,用于提取作为分库分表路由字段使用
```java
@Mapper
public interface IUserTakeActivityDao {
/**
* 插入用户领取活动信息
*
* @param userTakeActivity 入参
*/
@DBRouter(key = "uId")
void insert(UserTakeActivity userTakeActivity);
}
```
第二步: Mapper.xml中定义SQL语句
```xml
INSERT INTO user_take_activity
(u_id, take_id, activity_id, activity_name, take_date,
take_count, uuid, create_time, update_time)
VALUES
(#{uId}, #{takeId}, #{activityId}, #{activityName}, #{takeDate},
#{takeCount}, #{uuid}, now(), now())
```
第三步: 单元测试验证分库
```java
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTakeActivityDaoTest {
private Logger logger = LoggerFactory.getLogger(ActivityDaoTest.class);
@Resource
private IUserTakeActivityDao userTakeActivityDao;
@Test
public void test_insert() {
UserTakeActivity userTakeActivity = new UserTakeActivity();
userTakeActivity.setuId("Uhdgkw766120d"); // 1库:Ukdli109op89oi 2库:Ukdli109op811d
userTakeActivity.setTakeId(121019889410L);
userTakeActivity.setActivityId(100001L);
userTakeActivity.setActivityName("测试活动");
userTakeActivity.setTakeDate(new Date());
userTakeActivity.setTakeCount(10);
userTakeActivity.setUuid("Uhdgkw766120d");
userTakeActivityDao.insert(userTakeActivity);
}
}
```
> 测试中分别验证了不同的 uId 主要是为了解决数据散列到不同库表中去
### 分库分表案例
第一步: 在需要使用数据库路由的DAO方法上加入分表注解
```java
@Mapper
@DBRouterStrategy(splitTable = true)
public interface IUserStrategyExportDao {
/**
* 新增数据
* @param userStrategyExport 用户策略
*/
@DBRouter(key = "uId")
void insert(UserStrategyExport userStrategyExport);
/**
* 查询数据
* @param uId 用户ID
* @return 用户策略
*/
@DBRouter
UserStrategyExport queryUserStrategyExportByUId(String uId);
}
```
> - @DBRouterStrategy(splitTable = true) 配置分表信息,配置后会通过数据库路由组件把sql语句添加上分表字段,比如表 user 修改为 user_003
> - @DBRouter(key = "uId") 设置路由字段
> - @DBRouter 未配置情况下走默认字段,routerKey: uId
第二步: Mapper.xml中定义SQL语句
```xml
INSERT INTO user_strategy_export
(u_id, activity_id, order_id, strategy_id, strategy_mode,
grant_type, grant_date, grant_state, award_id, award_type,
award_name, award_content, uuid, create_time, update_time)
VALUES
(#{uId},#{activityId},#{orderId},#{strategyId},#{strategyMode},
#{grantType},#{grantDate},#{grantState},#{awardId},#{awardType},
#{awardName},#{awardContent},#{uuid},now(),now())
```
> 正常写 SQL 语句即可,如果你不使用注解 @DBRouterStrategy(splitTable = true) 也可以使用 `user_strategy_export_003`
第三步: 单元测试验证分库分表
```java
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserStrategyExportDaoTest {
private Logger logger = LoggerFactory.getLogger(UserStrategyExportDaoTest.class);
@Resource
private IUserStrategyExportDao userStrategyExportDao;
@Resource
private Map idGeneratorMap;
@Test
public void test_insert() {
UserStrategyExport userStrategyExport = new UserStrategyExport();
userStrategyExport.setuId("Uhdgkw766120d");
userStrategyExport.setActivityId(idGeneratorMap.get(Constants.Ids.ShortCode).nextId());
userStrategyExport.setOrderId(idGeneratorMap.get(Constants.Ids.SnowFlake).nextId());
userStrategyExport.setStrategyId(idGeneratorMap.get(Constants.Ids.RandomNumeric).nextId());
userStrategyExport.setStrategyMode(Constants.StrategyMode.SINGLE.getCode());
userStrategyExport.setGrantType(1);
userStrategyExport.setGrantDate(new Date());
userStrategyExport.setGrantState(1);
userStrategyExport.setAwardId("1");
userStrategyExport.setAwardType(Constants.AwardType.DESC.getCode());
userStrategyExport.setAwardName("IMac");
userStrategyExport.setAwardContent("奖品描述");
userStrategyExport.setUuid(String.valueOf(userStrategyExport.getOrderId()));
userStrategyExportDao.insert(userStrategyExport);
}
@Test
public void test_select() {
UserStrategyExport userStrategyExport = userStrategyExportDao.queryUserStrategyExportByUId("Uhdgkw766120d");
logger.info("测试结果:{}", JSON.toJSONString(userStrategyExport));
}
}
```
第四步: 测试结果
```text
21:05:52.050 INFO 86968 --- [ main] c.i.l.t.dao.UserStrategyExportDaoTest : Started UserStrategyExportDaoTest in 6.103 seconds (JVM running for 7.51)
21:05:52.292 INFO 86968 --- [ main] c.b.m.db.router.DBRouterJoinPoint : 数据库路由 method:queryUserStrategyExportByUId dbIdx:1 tbIdx:3
21:05:52.800 INFO 86968 --- [ main] c.i.l.t.dao.UserStrategyExportDaoTest : 测试结果:{"activityId":120405215,"awardContent":"test","awardId":"1","awardName":"IMac","awardType":1,"createTime":1633006252000,"grantDate":1633006252000,"grantState":1,"grantType":1,"id":1,"orderId":1443558966104850432,"strategyId":42480428672,"strategyMode":1,"uId":"Uhdgkw766120d","updateTime":1633006252000,"uuid":"1443558966104850432"}
```