Sharding-JDBC作为时下流行的分库分表工具,自有其魅力之处;
这里,我也写过两篇文章关于《SpringBoot入门建站全系列(二十四)使用Sharding-JDBC进行分库分表》和《Spring整合Sharding-JDBC分库分表详情》
阿里的Java开发手册的 MySQL 数据库–》建表规约–》第14条提到:单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表,当然,这不是绝对的,如果我们的数据呈现一定的规律,就是历史数据使用不频繁或基本不使用,也可以考虑分表存储几个月前的数据。所以,我这地方想说的是,当我们考虑分库分表时,应该先考虑是否需要分库,如果不需要分库,是否需要分页查询,如果不需要分页(如果自己实现归并分页另说),可以不使用Sharding-JDBC了;Mybatis就可以帮你实现!
注:网上也有人用mybatis分库,建议不要这样搞,mybatis分库要求当前用户可以操作其他数据库,这样看运维不打死你。
阿里的Java开发手册: https://www.pomit.cn/develops/aliJava2.html 我这里就有一份可以在线阅读。
首发地址:
品茗IT-同步发布
如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。
当年看到Mybatis的 符 号 , 第 一 反 应 就 是 , 肯 定 又 是 说 符号,第一反应就是,肯定又是说 符号,第一反应就是,肯定又是说和#的区别了,没错,这两个符号的区别特别重要,也经常被当作面试题来刁难初学者。
但是,它真的是太普通的一个概念,KaTeX parse error: Expected 'EOF', got '#' at position 9: 就是字符串替换,#̲是变量替换。也会有长者告诉你,…,会导致SQL注入的。其实,这只是使用场景的问题。
所以,我们可以使用$来进行表名的动态设置。
比如,我们打算对聊天记录做分表操作,最近一个月的聊天记录存储在t_chat_info表中,历史数据使用房间ID取余的形式分散在其他10个表中,此时,我们可以定义实体ChatInfo(对应表t_chat_info),中有一个字段叫liveId(房间ID对应数据库的live_id),是一个数字类型,可以作为分表字段。
根据liveId取余,获取到表名t_chat_info_x。
public ChatInfo findByChatNoAndLiveId(Integer liveId, Long id) {
String tableName = "t_chat_info_" + liveId % 10;
return chatInfoMapper.findByCondition(id, tableName);
}
使用${tableName}替换tableName参数,实现不同表查询数据。
@Select({
""})
ChatInfo findByCondition(@Param("id") Long id, @Param("tableName") String tableName);
bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值。
OGNL是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。
OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用。
Mybatis使用OGNL,可以动态替换sql语句中的变量。
MyBatis常用OGNL表达式(来源):
上述内容只是合适在MyBatis中使用的OGNL表达式.
有了bind,我们就可以将分表策略固定写在类中的静态方法,或者对象方法。
比如,我们打算对聊天记录做分表操作,最近一个月的聊天记录存储在t_chat_info表中,历史数据使用房间ID取余的形式分散在其他10个表中,此时,我们可以定义实体ChatInfo(对应表t_chat_info),中有一个字段叫liveId(房间ID对应数据库的live_id),是一个数字类型,可以作为分表字段。
我们在ChatInfo实体中定义findTable静态方法:
public static String findTable(Integer liveId) {
int index = liveId % 10;
String tableName = "t_chat_info_" + index;
return tableName;
}
使用@class@method(args)调用类的静态方法方式调用ChatInfo中的findTable方法,获取表名.
@Select({
""})
ChatInfo findByCondition(@Param("id") Long id, @Param("liveId") Integer liveId);
首先,我们还是使用实体ChatInfo。在实体ChatInfo中,定义两个静态方法:
根据分表字段找到单个表:
public static String findTable(Integer liveId) {
int index = liveId % 10;
String tableName = "t_chat_info_" + index;
return tableName;
}
根据分表字段的起始限制找到多个表:
public static String[] findTables(Integer start, Integer end) {
List<String> tables = new ArrayList<>();
for(int i = start; i <= end; i++){
tables.add("t_chat_info_" + i);
}
String[] arr = new String[0];
return tables.toArray(arr);
}
${tableName}为静态方法findTable指定的唯一表名。切记要带分表字段,且能根据分表字段计算出分表。
@Insert({
""})
int save(ChatInfo item);
${tableName}为静态方法findTable指定的唯一表名。切记要带分表字段,且能根据分表字段计算出分表。
@Delete({
""
})
int delete(@Param("paramIn") ChatInfo paramIn);
${tableName}为静态方法findTable指定的唯一表名。切记要带分表字段,且能根据分表字段计算出分表。
@Update({
""
})
int update(@Param("paramIn") ChatInfo updateIn);
${tableName}为静态方法findTable指定的唯一表名。切记要带分表字段,且能根据分表字段计算出分表。
@Select({
""})
ChatInfo findByCondition(@Param("id") Long id, @Param("liveId") Integer liveId);
使用findTables计算的patternTables来做mybatis的foreach循环。使用union来连接查询结果。
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
Union All:对两个结果集进行并集操作,包括重复行,不进行排序;
@Select({
""})
ChatInfo findRange(@Param("start") Integer start, @Param("end") Integer end, @Param("deleteFlag") Integer deleteFlag);
Spring项目快速开发工具:
一键快速构建Spring项目工具
一键快速构建SpringBoot项目工具
一键快速构建SpringCloud项目工具
一站式Springboot项目生成
Mysql一键生成Mybatis注解Mapper
Spring组件化构建
SpringBoot组件化构建
SpringCloud服务化构建