Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例
前言
在某些情況下,需要將大量數(shù)據(jù)分散到多個(gè)數(shù)據(jù)表中,這樣可以提高數(shù)據(jù)庫的查詢效率和數(shù)據(jù)處理能力。按天分表就是一種常見的數(shù)據(jù)分表策略,它將每天的數(shù)據(jù)放到一個(gè)獨(dú)立的數(shù)據(jù)表中,可以方便地進(jìn)行數(shù)據(jù)查詢和備份。但是,為了實(shí)現(xiàn)按天分表需要?jiǎng)討B(tài)表名的支持,即在創(chuàng)建表時(shí)根據(jù)當(dāng)前日期自動(dòng)生成表名。這樣可以確保每天數(shù)據(jù)都存放在不同的表中,避免數(shù)據(jù)重復(fù)或覆蓋的情況。同時(shí),動(dòng)態(tài)表名還可以幫助開發(fā)人員更方便地管理數(shù)據(jù),例如刪除過期數(shù)據(jù)表等。因此,使用動(dòng)態(tài)表名是按天分表的必要條件之一。
例如:t_user_20230901、t_user_20230902、t_user_20230903…
一、方案一(動(dòng)態(tài)傳參)
使用方法(Mapper自定義SQL)
坐標(biāo)依賴
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency>
數(shù)據(jù)源配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
實(shí)體類
@Data
@TableName("t_user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField("name")
private String name;
}
這里的@TableName("t_user")映射表名不需要帶上日期后綴
Mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 方法1
@Select("Select * from ${tableName}")
List<User> getUserInfo(@Param("tableName") String tableName);
// 方法2
List<User> getUserInfoMP(String tableName);
}
MapperXML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xx.xx.mapper.UserMapper">
<select id="getUserInfoMP" resultType="com.xx.xx.entity.User" >
select * from ${tableName} order by phone_number ASC
</select>
</mapper>
具體使用
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
void query(){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String rDay = LocalDateTime.now().format(formatter);
String tableName = "t_user_" + rDay;
List<User> list1 = userMapper.getUserInfo(tableName);
List<User> list2 = userMapper.getUserInfoMP(tableName);
}
}
二、方案二(DynamicTableNameInnerInterceptor插件)
使用方法(插件配置+ThreadLocal+輔助類)
配置類
@Configuration
@MapperScan(basePackages = {"com.xx.**.mapper"})
public class MybatisPlusConfig {
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//動(dòng)態(tài)表名
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
//可以傳多個(gè)表名參數(shù),指定哪些表使用DayTableNameHandler處理表名稱
dynamicTableNameInnerInterceptor.setTableNameHandler(new DayTableNameHandler("t_user"));
//以攔截器的方式處理表名稱
//可以傳遞多個(gè)攔截器,即:可以傳遞多個(gè)表名處理器TableNameHandler
mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
return mybatisPlusInterceptor;
}
}
輔助類
/**
* 按天參數(shù),組成動(dòng)態(tài)表名
*/
public class DayTableNameHandler implements TableNameHandler {
//用于記錄哪些表可以使用該動(dòng)態(tài)表名處理器(即哪些表需要分表)
private List<String> tableNames;
//構(gòu)造函數(shù),構(gòu)造動(dòng)態(tài)表名處理器的時(shí)候,傳遞tableNames參數(shù)
public DayTableNameHandler(String ...tableNames) {
this.tableNames = Arrays.asList(tableNames);
}
//每個(gè)請(qǐng)求線程維護(hù)一個(gè)day數(shù)據(jù),避免多線程數(shù)據(jù)沖突。所以使用ThreadLocal
private static final ThreadLocal<String> DAY_DATA = new ThreadLocal<>();
//設(shè)置請(qǐng)求線程的day數(shù)據(jù)
public static void setData(String day) {
DAY_DATA.set(day);
}
//刪除當(dāng)前請(qǐng)求線程的day數(shù)據(jù)
public static void removeData() {
DAY_DATA.remove();
}
//動(dòng)態(tài)表名接口實(shí)現(xiàn)方法
@Override
public String dynamicTableName(String sql, String tableName) {
if (this.tableNames.contains(tableName)){
return tableName + "_" + DAY_DATA.get(); //表名增加后綴
}else{
return tableName; //表名原樣返回
}
}
}
具體使用
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserService userService;
void query(){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String rDay = LocalDateTime.now().format(formatter);
DayTableNameHandler.setData(rDay);
List<User> list = userService.list();
// 用完即銷毀
DayTableNameHandler.removeData();
}
}
這里可以自行打印SQL語句驗(yàn)證 Select * from t_user_20230909
三、方案三(DynamicTableNameInnerInterceptor插件、省略輔助類)
這里可以直接配置DynamicTableNameInnerInterceptor插件做簡單的使用,但是用法相對(duì)固定,不能根據(jù)實(shí)際情況控制實(shí)體類所映射的表名,原因是被統(tǒng)一攔截
使用方法(插件配置+ThreadLocal)
配置類
@Configuration
@MapperScan(basePackages = {"com.xx.**.mapper"})
public class MybatisPlusConfig {
public static ThreadLocal<String> myTableName = new ThreadLocal<>();
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//動(dòng)態(tài)表名
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
HashMap<String, TableNameHandler> map = new HashMap<String, TableNameHandler>(2) {{
put("t_user", (sql, tableName) -> {
return myTableName.get();
});
}};
dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
myTableName.remove();
return mybatisPlusInterceptor;
}
}
具體使用
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserService userService;
void query(){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String rDay = LocalDateTime.now().format(formatter);
DayTableNameHandler.setData(rDay);
String tableName = "t_user" + rDay;
MybatisPlusConfig.myTableName.set(tableName);
List<User> list = userService.list();
}
}
總結(jié)
三種方法可以結(jié)合實(shí)際需要選擇,使用Mapper自定義SQL要注意SQL注入,使用線程池的方式要記得清理。
注意
Threadlocal 中的數(shù)據(jù)在AOP中最好自己釋放掉 ,spring是用的線程池,如果不清理掉會(huì)影響線程下次使用的程序。
到此這篇關(guān)于Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Mybatis-Plus 動(dòng)態(tài)表名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Mybatis動(dòng)態(tài)調(diào)用表名和字段名的解決方法
- mybatis plus 的動(dòng)態(tài)表名的配置詳解
- MyBatis攔截器動(dòng)態(tài)替換表名的方法詳解
- mybatis-plus動(dòng)態(tài)表名實(shí)現(xiàn)方法
- MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名
- MyBatis-Plus動(dòng)態(tài)表名的使用
- mybatis-plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例
- Mybatis動(dòng)態(tài)查詢字段及表名的實(shí)現(xiàn)
- Mybatis-Plus?動(dòng)態(tài)表名的實(shí)踐
- MyBatis-Plus 動(dòng)態(tài)表名的正確使用方式
相關(guān)文章
Jpa 如何使用@EntityListeners 實(shí)現(xiàn)實(shí)體對(duì)象的自動(dòng)賦值
這篇文章主要介紹了Jpa 如何使用@EntityListeners 實(shí)現(xiàn)實(shí)體對(duì)象的自動(dòng)賦值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
springboot v2.0.3版本多數(shù)據(jù)源配置方法
這篇文章主要介紹了springboot v2.0.3版本多數(shù)據(jù)源配置方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2018-11-11
SpringCloudAlibaba Nacos開啟鑒權(quán)解決跳過登錄頁面問題
對(duì)于Nacos,如果需要開啟權(quán)限控制,可以在 Nacos 控制臺(tái)上進(jìn)行配置,本文主要介紹了SpringCloudAlibaba Nacos開啟鑒權(quán)解決跳過登錄頁面問題,感興趣的可以了解一下2023-10-10
Java實(shí)現(xiàn)多用戶注冊(cè)登錄的幸運(yùn)抽獎(jiǎng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多用戶注冊(cè)登錄的幸運(yùn)抽獎(jiǎng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
java實(shí)現(xiàn)簡單的客戶信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單的客戶信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Java實(shí)現(xiàn)的貸款金額計(jì)算功能示例
這篇文章主要介紹了Java實(shí)現(xiàn)的貸款金額計(jì)算功能,結(jié)合實(shí)例形式分析了Java簡單數(shù)值運(yùn)算及類型轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
Maven引入本地Jar包并打包進(jìn)War包中的方法
本篇文章主要介紹了Maven引入本地Jar包并打包進(jìn)War包中的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
java通過HttpServletRequest獲取post請(qǐng)求中的body內(nèi)容的方法
本篇文章主要介紹了java通過HttpServletRequest獲取post請(qǐng)求中的body內(nèi)容的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02

