有些是按日期自动新建表,有些需要手动生成表
我这是新建活动时手动新建的表,一个活动一个表
一、先说分表写入和分表查询,使用mybatis-plus官方的DynamicTableNameInnerInterceptor插件,用法很简单
1、修改MybatisPlusConfig文件,新增一下代码
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
dynamicTableNameInnerInterceptor.setTableNameHandler(new MyTableNameHandler());//动态表名插件
mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
整体代码如下:
@Configuration
public class MybatisPlusConfig {
/**
* 配置分页等
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
dynamicTableNameInnerInterceptor.setTableNameHandler(new MyTableNameHandler());//动态表名插件
mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
// 分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表更新与删除
mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
}
2、新增TableNameHandler文件
public class MyTableNameHandler implements TableNameHandler {
private static final ThreadLocal<String> SUFFIX = new ThreadLocal<>();
public static void setData(String suffix) {
SUFFIX .set(suffix);
}
@Override
public String dynamicTableName(String sql, String tableName) {
String suffix = SUFFIX .get();
if(StringUtils.isNotBlank(suffix)){
SUFFIX .remove();
return tableName + suffix;
}
return tableName;
}
}
3、使用方法
查询使用:
在查询前加入以下代码即可
MyTableNameHandler.setData("_"+表名称);
比如:user表,加入以上代码就会变为user_20230101之类的
插入使用:
用法类似,也在写入以上代码,可以完善一下
public boolean save(String dynamicTableName, Users users) {
//将动态表名放到请求参数中(表名)
if(StringUtils.isNotBlank(dynamicTableName)){
MyTableNameHandler.setData("_"+dynamicTableName);
}
//和以前使用一样
userMapper.insert(users);
}
二、搭配代码自动建表
1、新建ShardTableHandler数据库操作类
@Component
public class ShardTableHandler {
/**
* 引入数据源,也可以是 DruidDataSource,此处根据项目配置来定
*/
@Resource
private DruidDataSource dataSource;
/**
* 验证表是否存在,按xxx维度进行分表
*/
public void checkExistTable(String tableName) {
Connection conn = null;
try {
conn = dataSource.getConnection();
String[] types = new String[]{"TABLE", "VIEW"};
// 查询当前数据源下的表数据
ResultSet rs = conn.getMetaData().getTables(conn.getCatalog(), conn.getSchema(), "%", types);
boolean exist = false;
// 判断是否存在
while (rs.next()) {
String tableStr = rs.getString("TABLE_NAME");
if (tableStr.equals(tableName)) {
exist = true;
break;
}
}
// 不存在则创建
if (!exist) {
System.out.println("创建表");
// 获取文件的URL
File file = ResourceUtils.getFile("classpath:create_user.sql");
// 转成string输入文本
String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
// 获取sql
String sql = String.format(content, tableName);
PreparedStatement ps = conn.prepareStatement(sql);
ps.execute();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2、新建create_user.sql数据库建表文件
CREATE TABLE `%s` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`openid` varchar(40) COLLATE utf8mb4_bin NOT NULL,
`user_name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',
`user_phone` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '手机号',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`headimgurl` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uni_openid` (`openid`) USING BTREE COMMENT '唯一openid',
UNIQUE KEY `uni_phone` (`user_phone`) USING BTREE COMMENT '唯一手机号'
) ENGINE=InnoDB AUTO_INCREMENT=185 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC;
3、引入与使用
//引入
@Resource
private ShardTableHandler shardTableHandler;
随意在需要建表前调用此方法即可新建数据库表
//date是日期区分|使用其他区分也行
shardTableHandler.checkExistTable("user_"+date);