本文小编为大家详细介绍“springboot按月分表的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“springboot按月分表的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
在实际工作中,会遇到业务比较集中的情况,随着时间推延,这部分业务关联的mysql表就会越来越大,十分臃肿。尽管在项目架构上做了读写分离,也会导致查询的时候出现比较慢的情况,导致线上慢查询的出现。
这种情况下导致的慢查询,单纯从sql优化的角度是无法解决的,此时我们就会用到分库分表。由于我们目前的问题是部分mysql表比较大,采用分表的方式即可解决,本文主要讨论分表的情况。
垂直分表
简单理解:把同一个表中的数据按列拆分
到不同的表中。
所谓的垂直分表指的是将表结构按照功能模块、关系密切程度划分出来,部署到不同的库或者不同的表中。
水平分表
简单理解:把同一个表中的数据按行拆分
到不同的表中。
所谓的水平分表,即将数据按照某种规则存储到不同的表中。例如日志表,可以使用按月或者按天分表,即每个月的日志数据单独存储在一张表中。这些表同时属于一张主表,拥有相同的表结构,但查询时可以大大减轻主表查询的负担。
主要使用mybatis-plus提供的功能来实现功能。
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency>
# mybatis-plus 配置 mybatis-plus.configuration.call-setters-on-nulls=true # xml 文件路径 mybatis-plus.mapper-locations=classpath*:mapping/*.xml # entity 文件路径 mybatis-plus.type-aliases-package=com.geniuworks.bot.entity # 打印sql语句执行日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl # 需要按月分表的表名 mp.tableNames=message
MybatisPlusConfig配置类实现:
package com.geniuworks.bot.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.parsers.DynamicTableNameParser; import com.baomidou.mybatisplus.extension.parsers.ITableNameHandler; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.geniuworks.bot.entity.Tables; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; /** * @Author dingws * @PackageName * @Package * @Date 2022/1/5 1:53 下午 * @Version 1.0 */ @Configuration @Slf4j public class MybatisPlusConfig { @Autowired private Tables tableNames; /** * * @return */ @Bean public PaginationInterceptor paginationInterceptor(){ PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser(); dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2){{ //涉及表集合 List<String> tables = tableNames.getTableNames(); //动态表规则 初始表名+_+code tables.forEach(tableTitle -> put(tableTitle,(metaObject, sql, tableName) -> tableName + String.valueOf(getParamValue("month",metaObject)))); }}); paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser)); return paginationInterceptor; } /** * * @param title * @param metaObject * @return */ private Object getParamValue(String title, MetaObject metaObject){ //获取参数 Object originalObject = metaObject.getOriginalObject(); JSONObject originalObjectJSON = JSON.parseObject(JSON.toJSONString(originalObject)); JSONObject boundSql = originalObjectJSON.getJSONObject("boundSql"); JSONObject parameterObject = boundSql.getJSONObject("parameterObject"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM"); if(parameterObject.get(title) == null){ return ""; } Date date = parameterObject.getObject(title, Date.class); log.info("param value = " + formatter.format(date)); return "_" + formatter.format(date); } }
Tables类实现:
package com.geniuworks.bot.entity; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import java.util.List; /** * @Author dingws * @PackageName * @Package * @Date 2022/1/5 2:18 下午 * @Version 1.0 */ @Configuration @ConfigurationProperties("mp") @Data public class Tables { private List<String> tableNames; }
在使用的时候,只需要在mysql表对应的entity里添加一个字段month即可。
如果month不为空就会按照month的日期所在的月份对数据库表明进行动态拼接。如果month为空则不进行拼接,直接访问总表。
entity类实现:
package com.geniuworks.bot.entity; import java.util.Date; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Message { private String id; private String sessionId; private Date createdTime; private String content; // 根据该字段所在的月分,区分访问的表名 private Date month; }
mapper类实现:
package com.geniuworks.bot.mapper; import com.geniuworks.bot.entity.Message; import com.geniuworks.bot.vo.MessageVo; import com.geniuworks.bot.vo.StatisticsVo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.util.Date; import java.util.List; import java.util.Map; @Mapper public interface MessageMapper { /** * insert record to table * @param record the record * @return insert count */ int insert(Message record); /** * insert record to table selective * @param record the record * @return insert count */ int insertSelective(Message record); /** * update record selective * @param record the updated record * @return update count */ int updateByPrimaryKeySelective(Message record); /** * update record * @param record the updated record * @return update count */ int updateByPrimaryKey(Message record);
需要手动把当年需要的数据库手动创建出来,命名规则对应MybatisPlusConfig类中的拼接规则。
由于我一直用的是mybatis组件,需要升级为mybatis-plus,在升级的过程中出现如下的问题。
问题原因: pom文件依赖的是mybatis-plus,配置文件中使用的是mybatis的配置,导致mybatis加载失败。
解决方法:把配置文件的mybatis配置改为mybatis-plus配置
问题原因: 在未升级成mybatis-plus之前,可以直接放回数据库中的字段命名。 升级之后,mybatis-plus将放回字段自动映射为entity中的字段命名。
解决方案: 梳理受到影响的代码逻辑,更新使用的字段命名。
读到这里,这篇“springboot按月分表的方法是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。