springboot 按月分表的實(shí)現(xiàn)方式
一、項(xiàng)目背景
在實(shí)際工作中,會遇到業(yè)務(wù)比較集中的情況,隨著時間推延,這部分業(yè)務(wù)關(guān)聯(lián)的mysql表就會越來越大,十分臃腫。盡管在項(xiàng)目架構(gòu)上做了讀寫分離,也會導(dǎo)致查詢的時候出現(xiàn)比較慢的情況,導(dǎo)致線上慢查詢的出現(xiàn)。
這種情況下導(dǎo)致的慢查詢,單純從sql優(yōu)化的角度是無法解決的,此時我們就會用到分庫分表。由于我們目前的問題是部分mysql表比較大,采用分表的方式即可解決,本文主要討論分表的情況。
1、分表的方式
- 垂直分表
簡單理解:把同一個表中的數(shù)據(jù)按列拆分到不同的表中。
所謂的垂直分表指的是將表結(jié)構(gòu)按照功能模塊、關(guān)系密切程度劃分出來,部署到不同的庫或者不同的表中。
- 水平分表
簡單理解:把同一個表中的數(shù)據(jù)按行拆分到不同的表中。
所謂的水平分表,即將數(shù)據(jù)按照某種規(guī)則存儲到不同的表中。例如日志表,可以使用按月或者按天分表,即每個月的日志數(shù)據(jù)單獨(dú)存儲在一張表中。這些表同時屬于一張主表,擁有相同的表結(jié)構(gòu),但查詢時可以大大減輕主表查詢的負(fù)擔(dān)。
二、代碼實(shí)現(xiàn)
主要使用mybatis-plus提供的功能來實(shí)現(xiàn)功能。
1、pom文件依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
2、配置文件
# 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語句執(zhí)行日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl # 需要按月分表的表名 mp.tableNames=message
3、MybatisPlusConfig實(shí)現(xiàn)
MybatisPlusConfig配置類實(shí)現(xiàn):
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();
//動態(tài)表規(guī)則 初始表名+_+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){
//獲取參數(shù)
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類實(shí)現(xiàn):
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;
}
4、優(yōu)雅的使用
在使用的時候,只需要在mysql表對應(yīng)的entity里添加一個字段month即可。
如果month不為空就會按照month的日期所在的月份對數(shù)據(jù)庫表明進(jìn)行動態(tài)拼接。如果month為空則不進(jìn)行拼接,直接訪問總表。
entity類實(shí)現(xiàn):
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;
// 根據(jù)該字段所在的月分,區(qū)分訪問的表名
private Date month;
}
mapper類實(shí)現(xiàn):
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);
5、mysql表名拆分
需要手動把當(dāng)年需要的數(shù)據(jù)庫手動創(chuàng)建出來,命名規(guī)則對應(yīng)MybatisPlusConfig類中的拼接規(guī)則。

三、遇到的問題
由于我一直用的是mybatis組件,需要升級為mybatis-plus,在升級的過程中出現(xiàn)如下的問題。
1、Invalid bound statement (not found)
問題原因: pom文件依賴的是mybatis-plus,配置文件中使用的是mybatis的配置,導(dǎo)致mybatis加載失敗。
解決方法:把配置文件的mybatis配置改為mybatis-plus配置
2、resultType=“java.util.Map”,返回字段名被包裝
問題原因: 在未升級成mybatis-plus之前,可以直接放回?cái)?shù)據(jù)庫中的字段命名。 升級之后,mybatis-plus將放回字段自動映射為entity中的字段命名。
解決方案: 梳理受到影響的代碼邏輯,更新使用的字段命名。
到此這篇關(guān)于springboot 按月分表的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)springboot 按月分表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot+mybatis攔截器方法實(shí)現(xiàn)水平分表操作
- SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表
- SpringBoot實(shí)現(xiàn)分庫分表
- springboot+mybatis-plus基于攔截器實(shí)現(xiàn)分表的示例代碼
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫分表與讀寫分離的示例
- springboot整合shardingjdbc實(shí)現(xiàn)分庫分表最簡單demo
- springboot jpa分庫分表項(xiàng)目實(shí)現(xiàn)過程詳解
相關(guān)文章
Java實(shí)現(xiàn)添加文字水印&圖片水印的方法詳解
為圖片添加水印的主要作用是保護(hù)圖片版權(quán),防止圖片被未經(jīng)授權(quán)的人使用或傳播。本文為大家介紹了Java實(shí)現(xiàn)添加文字水印&圖片水印的具體方法,需要的可以參考一下2023-02-02
Spring mvc攔截器實(shí)現(xiàn)原理解析
這篇文章主要介紹了Spring mvc攔截器實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03
java 讀取網(wǎng)頁內(nèi)容的實(shí)例詳解
這篇文章主要介紹了java 讀取網(wǎng)頁內(nèi)容的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家學(xué)習(xí)理解這部分內(nèi)容,需要的朋友可以參考下2017-09-09
java.lang.NullPointerException 如何處理空指針異常的實(shí)現(xiàn)
這篇文章主要介紹了java.lang.NullPointerException 如何處理空指針異常的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
IDEA設(shè)置maven修改settings.xml配置文件無法加載倉庫的解決方案
這篇文章主要介紹了IDEA設(shè)置maven修改settings.xml配置文件無法加載倉庫的解決方案,幫助大家更好的利用IDEA進(jìn)行JAVA的開發(fā)學(xué)習(xí),感興趣的朋友可以了解下2021-01-01

