做网站开专票税钱是多少个点,公司黄页企业名录在哪里查,门户网站 建设 北京 航天,哈尔滨服务好的建站引言 随着互联网应用的快速发展#xff0c;数据量呈爆炸式增长。传统的单表设计在面对海量数据时显得力不从心#xff0c;容易出现性能瓶颈、查询效率低下等问题。为了提高数据库的扩展性和响应速度#xff0c;分表#xff08;Sharding#xff09;成为了一种常见的解决方案…引言 随着互联网应用的快速发展数据量呈爆炸式增长。传统的单表设计在面对海量数据时显得力不从心容易出现性能瓶颈、查询效率低下等问题。为了提高数据库的扩展性和响应速度分表Sharding成为了一种常见的解决方案。 在最近的工作中遇到了日志过大导致查询过慢的问题你可能疑问为啥日志要放到mysql中是因为这个日志只是跨系统之间接口的请求日志本文主要介绍Mybatis-plus动态表名处理器分表业务的实现。
1. 什么是分表为什么要分表 分表是指将一个大型的数据库表拆分成多个较小的表的技术每个小表存储部分原始表的数据。通过这种方式可以有效地减少单个表的数据量从而提升查询效率和系统整体性能。 为什么要分表啊Mysql是当前互联网系统中使用非常广泛的关系数据库具有ACID的特性。但是mysql的单表性能会受到表中数据量的限制主要原因是B树索引过大导致查询时索引无法全部加载到内存。读取磁盘的次数变多而磁盘的每次读取对性能都有很大的影响。 这时一个简单可行的方案就是分表(当然土豪也可以堆硬件)将一张数据量庞大的表的数据拆分到多个表中这同时也减少了B树索引的大小减少磁盘读取次数提高性能。
2. 分表策略
2.1 水平分表Horizontal Sharding
1水平分表是根据一定的规则将数据行分散到不同的物理表中。
2这种方式保持了表结构的一致性但数据被分布到了不同的物理位置。
3适用于数据量大、写操作频繁的场景。
2.2 垂直分表Vertical Sharding
1垂直分表是按照列来分割表将不同字段分配到不同的表中。
2主要目的是分离热点数据和非热点数据或减少单表的宽度。
3适用于某些字段访问频率远高于其他字段的情况。
3. 常见的分表技术
3.1 MyCat (原名MySQL Proxy) MyCat 是一个开源的分布式数据库系统它兼容 MySQL 协议支持 SQL 解析、SQL 路由等功能能够帮助开发者轻松实现读写分离、分库分表等复杂功能。对于使用 MySQL 数据库的 Java 应用来说MyCat 提供了一套完整的分表解决方案。
3.2 Apache ShardingSphere Apache ShardingSphere 是一套开源的分布式数据库中间件提供了透明化分片、分布式事务、数据加密等功能。它不仅支持 MySQL 和 PostgreSQL 等多种数据库还为应用程序屏蔽了底层复杂的分片逻辑使得开发人员可以专注于业务逻辑的实现。
3.3 TDDL (Taobao Distributed Database Layer) TDDL 是阿里巴巴内部使用的分布式数据库服务层主要用于解决高并发下的数据库连接池问题和分库分表。它提供了一个简单的 API 接口允许应用程序以一种非常自然的方式进行分片配置和管理。
3.4 分布式对象关系映射工具如 Hibernate Shards 一些 ORM 框架也提供了对分表的支持例如 Hibernate 的 Shards 扩展。这些工具可以在一定程度上简化分表逻辑的编码工作使开发者能够更加关注于业务模型的设计而非底层的数据管理细节。
4、使用Mybatis-plus的TableNameHandler动态表名处理器实现分表业务
4.1 优劣
1优势 简单易用对于已采用 MyBatis 或 MyBatis-Plus 的项目来说使用 TableNameHandler 实现分表逻辑非常直接不需要引入额外的中间件或大幅修改现有代码架构降低了迁移成本和技术复杂度。 轻量级集成由于是基于 MyBatis-Plus 进行扩展因此在集成方面更为轻便不需要复杂的配置过程能快速应用于开发环境。 灵活性高通过自定义 TableNameHandler可以根据具体的业务需求灵活地设置分表策略比如按时间、用户ID或其他业务维度进行分表。 2劣势 功能局限性与专门设计用于分布式数据库管理的解决方案如 Apache ShardingSphere 或 MyCat相比MyBatis-Plus 的 TableNameHandler 在处理复杂分库分表场景时显得力不从心。例如在需要跨多个数据库实例进行数据操作时TableNameHandler 可能无法提供足够的支持。 缺乏高级特性MyBatis-Plus 主要关注于简化数据库访问层的操作对于一些高级特性如分布式事务、全局唯一ID生成等支持有限这些往往是大规模分布式系统中不可或缺的部分。 性能优化空间有限虽然 MyBatis-Plus 提供了多种性能优化措施但在面对超大规模数据集或极高并发请求时可能还需要依赖更专业的数据库中间件来进行深层次的性能调优。 维护成本当分表规则变得越来越复杂时使用 TableNameHandler 可能会导致维护难度增加尤其是在需要频繁调整分表策略的情况下。 总结而言如果项目的需求相对简单主要集中在单个数据库实例内并且团队对 MyBatis-Plus 已经有一定的熟悉度那么利用 TableNameHandler 实现分表是一个高效的选择。然而对于那些需要跨数据库实例、具备复杂查询要求或需要更多高级数据库管理特性的应用场景选择像 Apache ShardingSphere 或 MyCat 这样的专业工具可能是更好的解决方案。
4.2 详细实现介绍 描述 1这里以跨系统交互日志记录表为例实现分表业务 2当日志表数据越来越大查询效率越来越低我们除了添加索引之外也可以分表操作提升查询性能 ps其实也可以将之前的分页查询改为列表查询只会进行上一页下一页操作。因为分页查询会计算总数当数据量过大时也会导致查询过慢 4.2.1 表信息
CREATE TABLE ihm_system_interaction_log (id bigint(20) NOT NULL COMMENT 主键,path varchar(255) NOT NULL COMMENT 路径,request_part tinyint(4) DEFAULT NULL COMMENT 请求方1-患者端 2-医生端 3-his 4-京通微信支付 5-首信医保支付,response_part tinyint(4) DEFAULT NULL COMMENT 响应方1-患者端 2-医生端 3-his 4-京通微信支付 5-首信医保支付 6-114公众号支付 7-支付宝支付,recording_part tinyint(4) DEFAULT NULL COMMENT 记录方1-患者端 2-医生端\n同一次请求请求方和响应方都为患者端或医生端时需要分别记录如果请求方和响应方为医生端和第三方his、首信等时仅记录医生端日志,request_time datetime DEFAULT NULL COMMENT 请求时间,response_time datetime DEFAULT NULL COMMENT 响应时间,day varchar(50) DEFAULT NULL COMMENT 日期根据请求时间生成方便检查、统计,month int(11) DEFAULT NULL COMMENT 月份,loss_time int(11) DEFAULT NULL COMMENT 耗时,result_code int(11) DEFAULT NULL COMMENT 响应结果 0-成功 -1 失败,err_info longtext COMMENT 错误堆栈限制长度超长的截取,request_param varchar(64) DEFAULT NULL COMMENT 请求参数,request_body longtext COMMENT 请求体可能是json、可能是xml,response_body longtext COMMENT 响应体可能是json、可能是xml,message_id varchar(50) DEFAULT NULL COMMENT 消息id一个流程的接口日志应该是同一个message_id,order_seq varchar(50) DEFAULT NULL COMMENT 订单编号涉及订单接口、应该要有对应信息,user_id_type tinyint(4) DEFAULT NULL COMMENT 证件类型,user_id_no varchar(50) DEFAULT NULL COMMENT 用户证件号码,user_id bigint(20) DEFAULT NULL COMMENT 用户id,patient_id_type tinyint(4) DEFAULT NULL COMMENT 证件类型,patient_id_no varchar(50) DEFAULT NULL COMMENT 用户证件号码,patient_id bigint(20) DEFAULT NULL COMMENT 用户id,trace_id varchar(255) DEFAULT NULL COMMENT 日志traceId接口流程的trace_id根据不同方存不同的trace_id方便在kibana查看,hospital_id bigint(20) DEFAULT NULL COMMENT 医院id,org_code varchar(50) DEFAULT NULL COMMENT 机构编码,deleted int(11) DEFAULT NULL,create_time datetime DEFAULT NULL COMMENT 创建时间,create_by varchar(20) DEFAULT NULL COMMENT 创建人,update_time datetime DEFAULT NULL COMMENT 更新时间,update_by varchar(20) DEFAULT NULL COMMENT 更新人,version int(11) DEFAULT NULL COMMENT 版本,PRIMARY KEY (id),KEY order_seq (order_seq),KEY patient_id_no (patient_id_no),KEY user_id_no (user_id_no),KEY ihm_system_interaction_log_create_time_index (create_time),KEY ihm_system_interaction_log_hospital_id_index (hospital_id),KEY org_code (org_code),KEY trace_id (trace_id),KEY message_id (message_id),KEY user_id (user_id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT跨系统交互日志记录表;
4.2.2 表名按月处理器 月份动态表名处理器 package com.chinaunicom.medical.ihm.handler;import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.List;Slf4j
public class MonthTableNameHandler implements TableNameHandler {//用于记录哪些表可以使用该月份动态表名处理器即哪些表按月分表private ListString tableNames;//构造函数构造动态表名处理器的时候传递tableNames参数public MonthTableNameHandler(String ...tableNames) {this.tableNames Arrays.asList(tableNames);}//每个请求线程维护一个month数据避免多线程数据冲突。所以使用ThreadLocalprivate static final ThreadLocalString MONTH_DATA new ThreadLocal();//设置请求线程的month数据public static void setData(String month) {MONTH_DATA.set(month);}//删除当前请求线程的month数据public static void removeData() {MONTH_DATA.remove();}//动态表名接口实现方法Overridepublic String dynamicTableName(String sql, String tableName) {if (this.tableNames.contains(tableName)){//表名增加月份后缀return tableName _ MONTH_DATA.get();}else{//表名原样返回return tableName;}}}4.2.3 MybatisPlusConfig配置 这里只添加动态表名处理器 (DynamicTableNameInnerInterceptor)即可。 动态表名处理器 (DynamicTableNameInnerInterceptor)通过实现动态表名处理逻辑使得某些表在执行 SQL 操作时能够根据特定规则如时间选择不同的物理表。 乐观锁插件 (OptimisticLockerInnerInterceptor)提供乐观锁机制防止并发修改数据时出现的数据覆盖问题。 分页插件 (PaginationInnerInterceptor)支持数据库查询结果的分页操作便于处理大量数据。 package com.chinaunicom.medical.ihm.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.chinaunicom.medical.ihm.core.model.DateMetaObjectHandler;
import com.chinaunicom.medical.ihm.handler.MonthTableNameHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;Configuration
public class PortalMybatisPlusConfig {BeanPrimarypublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor new DynamicTableNameInnerInterceptor();dynamicTableNameInnerInterceptor.setTableNameHandler(//可以传多个表名参数指定哪些表使用MonthTableNameHandler处理表名称new MonthTableNameHandler(ihm_system_interaction_log));//以拦截器的方式处理表名称interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}4.2.4 加载Mybatis-Plus配置 这里只需要添加AutoConfigureBefore(value PortalMybatisPlusConfig.class)即可。如果你还有别的通用mybatis-plus配置可以使用ComponentScan中的excludeFilters排除。避免配置冲突。 主要注解及功能 SpringBootApplication 这是一个组合注解包含了 Configuration, EnableAutoConfiguration 和 ComponentScan。它简化了 Spring Boot 应用程序的基本设置和自动配置。 EnableScheduling 开启对计划任务的支持允许使用 Scheduled 注解来定义定时执行的任务。 ComponentScan 指定了组件扫描的基础包为 com.chinaunicom.medical同时通过 excludeFilters 排除了 MybatisPlusConfig 类的扫描。这意味着在组件扫描过程中不会加载或处理 MybatisPlusConfig 这个类。 AutoConfigureBefore(value PortalMybatisPlusConfig.class) 表明当前的自动配置类将在 PortalMybatisPlusConfig 之前被加载和配置。这种配置顺序控制对于确保某些特定的 Bean 在其他 Bean 之前初始化是必要的。 核心类和方法 PortalApplication 类 包含了应用程序的入口方法 main通过调用 SpringApplication.run(PortalApplication.class, args) 来启动 Spring Boot 应用程序。 PortalMybatisPlusConfig 提供了 MyBatis-Plus 相关的配置如动态表名处理器、乐观锁插件和分页插件等。 ComponentScan(value {com.chinaunicom.medical}, excludeFilters {ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes {com.chinaunicom.medical.ihm.core.web.MybatisPlusConfig.class})})
SpringBootApplication
EnableScheduling
AutoConfigureBefore(value PortalMybatisPlusConfig.class)
public class PortalApplication {public static void main(String[] args) {SpringApplication.run(PortalApplication.class, args);}}
4.2.5 定时按月分表 定时创建下月表已存在不会创建 启动时创建当月与下月表 package com.chinaunicom.medical.ihm.securityaudit.repository.schedule;import com.chinaunicom.medical.ihm.securityaudit.repository.SystemInteractionLogService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;Service
public class IhmSystemInteractionLogSchedule {private static final Logger logger LoggerFactory.getLogger(IhmSystemInteractionLogSchedule.class);Resourceprivate SystemInteractionLogService systemInteractionLogService;PostConstructpublic void executeOnStartup() {// 启动时执行的任务逻辑启动后执行一次创建当月与下月表createIhmSystemInteractionLogNowTable();createIhmSystemInteractionLogTable();}/*** 启动后创建一次当月表已存在不会创建*/public void createIhmSystemInteractionLogNowTable() {String tableName ihm_system_interaction_log_ LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyyMM)) ;logger.info(----开始创建当月表:{}, tableName);systemInteractionLogService.createIhmSystemInteractionLogTable(tableName);logger.info(----创建当月表结束:{}, tableName);}/*** 每天尝试创建下个月跨系统交互日志表已存在的不会创建*/Scheduled(cron 0 0 4 * * ?)public void createIhmSystemInteractionLogTable() {String tableName ihm_system_interaction_log_ LocalDateTime.now().plusMonths(1).format(DateTimeFormatter.ofPattern(yyyyMM)) ;logger.info(----开始创建下月表:{}, tableName);systemInteractionLogService.createIhmSystemInteractionLogTable(tableName);logger.info(----创建下月表结束:{}, tableName);}
}/*** author Administrator* description 针对表【ihm_system_interaction_log(跨系统交互日志记录表)】的数据库操作Service实现* createDate 2024-07-12 20:20:18*/
Service
Slf4j
public class SystemInteractionLogService extends ServiceImplSystemInteractionLogMapper, SystemInteractionLog{Resourceprivate SystemInteractionLogMapper systemInteractionLogMapper;/*** 创建跨系统交互日志表* param* return*/public void createIhmSystemInteractionLogTable(String tableName) {systemInteractionLogMapper.createSystemInteractionLogTable(tableName);}}
package com.chinaunicom.medical.ihm.securityaudit.repository.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaunicom.medical.ihm.securityaudit.repository.model.SystemInteractionLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;/*** author Administrator* description 针对表【ihm_system_interaction_log(跨系统交互日志记录表)】的数据库操作Mapper* createDate 2024-07-12 20:20:18* Entity com.chinaunicom.medical.ihm.models.po.SystemInteractionLog*/
Mapper
public interface SystemInteractionLogMapper extends BaseMapperSystemInteractionLog {/**** param tableName*/Update(CREATE TABLE if not EXISTS ${tableName} \n (id bigint(20) NOT NULL COMMENT 主键,\n path varchar(255) NOT NULL COMMENT 路径,\n request_part tinyint(4) DEFAULT NULL COMMENT 请求方1-患者端 2-医生端 3-his 4-京通微信支付 5-首信医保支付,\n response_part tinyint(4) DEFAULT NULL COMMENT 响应方1-患者端 2-医生端 3-his 4-京通微信支付 5-首信医保支付 6-114公众号支付 7-支付宝支付,\n recording_part tinyint(4) DEFAULT NULL COMMENT 记录方1-患者端 2-医生端\\n同一次请求请求方和响应方都为患者端或医生端时需要分别记录如果请求方和响应方为医生端和第三方his、首信等时仅记录医生端日志,\n request_time datetime DEFAULT NULL COMMENT 请求时间,\n response_time datetime DEFAULT NULL COMMENT 响应时间,\n day varchar(50) DEFAULT NULL COMMENT 日期根据请求时间生成方便检查、统计,\n month int(11) DEFAULT NULL COMMENT 月份,\n loss_time int(11) DEFAULT NULL COMMENT 耗时,\n result_code int(11) DEFAULT NULL COMMENT 响应结果 0-成功 -1 失败,\n err_info longtext COMMENT 错误堆栈限制长度超长的截取,\n request_param varchar(64) DEFAULT NULL COMMENT 请求参数,\n request_body longtext COMMENT 请求体可能是json、可能是xml,\n response_body longtext COMMENT 响应体可能是json、可能是xml,\n message_id varchar(50) DEFAULT NULL COMMENT 消息id一个流程的接口日志应该是同一个message_id,\n order_seq varchar(50) DEFAULT NULL COMMENT 订单编号涉及订单接口、应该要有对应信息,\n user_id_type tinyint(4) DEFAULT NULL COMMENT 证件类型,\n user_id_no varchar(50) DEFAULT NULL COMMENT 用户证件号码,\n user_id bigint(20) DEFAULT NULL COMMENT 用户id,\n patient_id_type tinyint(4) DEFAULT NULL COMMENT 证件类型,\n patient_id_no varchar(50) DEFAULT NULL COMMENT 用户证件号码,\n patient_id bigint(20) DEFAULT NULL COMMENT 用户id,\n trace_id varchar(255) DEFAULT NULL COMMENT 日志traceId接口流程的trace_id根据不同方存不同的trace_id方便在kibana查看,\n hospital_id bigint(20) DEFAULT NULL COMMENT 医院id,\n org_code varchar(50) DEFAULT NULL COMMENT 机构编码,\n deleted int(11) DEFAULT NULL,\n create_time datetime DEFAULT NULL COMMENT 创建时间,\n create_by varchar(20) DEFAULT NULL COMMENT 创建人,\n update_time datetime DEFAULT NULL COMMENT 更新时间,\n update_by varchar(20) DEFAULT NULL COMMENT 更新人,\n version int(11) DEFAULT NULL COMMENT 版本,\n PRIMARY KEY (id),\n KEY order_seq (order_seq),\n KEY patient_id_no (patient_id_no),\n KEY user_id_no (user_id_no),\n KEY ihm_system_interaction_log_create_time_index (create_time),\n KEY ihm_system_interaction_log_hospital_id_index (hospital_id),\n KEY org_code (org_code),\n KEY trace_id (trace_id),\n KEY message_id (message_id),\n KEY user_id (user_id)\n ) COMMENT跨系统交互日志记录表;)void createSystemInteractionLogTable(String tableName);
}
4.2.6 查询功能举例 怎么能查到指定表中的数据呢其实核心在于MonthTableNameHandler日期的处理这里指定日期后会被Mybatis-Plus拦截器处理拼上指定的后缀得到正确表名。 SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM);
String data simpleDateFormat.format(new Date());
if (StrUtil.isNotBlank(dto.getRequestTime())) {try {Date dt simpleDateFormat.parse(dto.getRequestTime());data simpleDateFormat.format(dt);} catch (ParseException e) {log.error(时间转换异常,e);}
}
MonthTableNameHandler.setData(data.replace(-, )); Overridepublic PageSystemInteractionLogInfoVO queryPage(LogQueryPageDTO dto) {Validator.validateNotNull(dto, 传参不能为空);log.info(传参信息:{}, JSONUtil.toJsonPrettyStr(dto));SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM);String data simpleDateFormat.format(new Date());if (StrUtil.isNotBlank(dto.getRequestTime())) {try {Date dt simpleDateFormat.parse(dto.getRequestTime());data simpleDateFormat.format(dt);} catch (ParseException e) {log.error(时间转换异常,e);}}MonthTableNameHandler.setData(data.replace(-, ));//1、构建分页条件PageSystemInteractionLog page new Page(dto.getCurrent(), dto.getSize());//2、分页查询PageSystemInteractionLog logPage lambdaQuery().eq(ObjectUtil.isNotEmpty(dto.getHospitalId()), SystemInteractionLog::getHospitalId, dto.getHospitalId()).eq(ObjectUtil.isNotEmpty(dto.getOrgCode()), SystemInteractionLog::getOrgCode, dto.getOrgCode()).eq(ObjectUtil.isNotEmpty(dto.getOrderSeq()), SystemInteractionLog::getOrderSeq, dto.getOrderSeq()).eq(ObjectUtil.isNotEmpty(dto.getUserId()), SystemInteractionLog::getUserId, dto.getUserId()).eq(StrUtil.isNotBlank(dto.getTraceId()), SystemInteractionLog::getTraceId,dto.getTraceId()).eq(StrUtil.isNotBlank(dto.getMessageId()), SystemInteractionLog::getMessageId,dto.getMessageId()).eq(ObjectUtil.isNotEmpty(dto.getRequestPart()), SystemInteractionLog::getRequestPart, dto.getRequestPart()).eq(ObjectUtil.isNotEmpty(dto.getResponsePart()), SystemInteractionLog::getResponsePart, dto.getResponsePart()).eq(ObjectUtil.isNotEmpty(dto.getRecordingPart()), SystemInteractionLog::getRecordingPart, dto.getRecordingPart()).eq(ObjectUtil.isNotEmpty(dto.getResultCode()), SystemInteractionLog::getResultCode, dto.getResultCode()).like(StrUtil.isNotBlank(dto.getPath()), SystemInteractionLog::getPath, dto.getPath()).ge(ObjectUtil.isNotEmpty(dto.getRequestTime()), SystemInteractionLog::getRequestTime, dto.getRequestTime()).le(ObjectUtil.isNotEmpty(dto.getResponseTime()), SystemInteractionLog::getResponseTime, dto.getResponseTime()).orderByDesc(SystemInteractionLog::getCreateTime).page(page);//3、封装返回结果PageSystemInteractionLogInfoVO returnPage new Page();BeanUtil.copyProperties(logPage,returnPage);ListSystemInteractionLog records logPage.getRecords();if(CollectionUtil.isNotEmpty(records)){returnPage.setRecords(BeanUtil.copyToList(records,SystemInteractionLogInfoVO.class));}return returnPage;}
4.2.7 保存功能举例 怎么能保存到指定表中的数据呢其实核心在于MonthTableNameHandler日期的处理这里指定日期后会被Mybatis-Plus拦截器处理拼上指定的后缀得到正确表名。 //保存数据到本月对应的表中 SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyyMM); String data simpleDateFormat.format(new Date()); MonthTableNameHandler.setData(data); Overridepublic boolean saveLog(SystemInteractionLogDto systemInteractionLogDto) {SystemInteractionLog systemInteractionLog BeanUtil.copyProperties(systemInteractionLogDto, SystemInteractionLog.class);if (StringUtils.isNotBlank(systemInteractionLog.getDay()) systemInteractionLog.getDay().length() 10) {systemInteractionLog.setDay(systemInteractionLog.getDay().substring(0, 10));}systemInteractionLog.setMonth(Integer.valueOf(LocalDate.now().format(MONTH_FORMAT)));systemInteractionLog.setOrgCode(systemInteractionLogDto.getHospCode());String orderSeq systemInteractionLog.getOrderSeq();String inquiryNo null;String hospCode null;if (StringUtils.isBlank(orderSeq)) {if (StringUtils.isNotBlank(systemInteractionLog.getRequestParam()) systemInteractionLog.getRequestParam().contains(orderSeq)) {String requestParam systemInteractionLog.getRequestParam();String[] params requestParam.split(, -1);for (String param : params) {if (StringUtils.isBlank(orderSeq) (orderSeq.equals(param) || order_seq.equals(param))) {orderSeq param.split()[1];}if (StringUtils.isBlank(inquiryNo) (inquiryNo.equals(param) || inquiry_no.equals(param))) {inquiryNo param.split()[1];}if (StringUtils.isBlank(hospCode) (hosp_code.equals(param) || hospCode.equals(param))) {hospCode param.split()[1];}}}}if (StringUtils.isNotBlank(systemInteractionLog.getRequestBody())) {String requestBody systemInteractionLog.getRequestBody();if (StringUtils.isBlank(orderSeq)) {orderSeq getTargetValueByKey(requestBody, orderSeq);}if (StringUtils.isBlank(orderSeq)) {orderSeq getTargetValueByKey(requestBody, order_seq);}if (StringUtils.isBlank(inquiryNo)) {inquiryNo getTargetValueByKey(requestBody, inquiryNo);}if (StringUtils.isBlank(inquiryNo)) {inquiryNo getTargetValueByKey(requestBody, inquiry_no);}if (StringUtils.isBlank(hospCode)) {hospCode getTargetValueByKey(requestBody, hospCode);}if (StringUtils.isBlank(hospCode)) {hospCode getTargetValueByKey(requestBody, hosp_code);}}if (StringUtils.isNotBlank(systemInteractionLog.getResponseBody())) {String responseBody systemInteractionLog.getResponseBody();if (StringUtils.isBlank(orderSeq)) {orderSeq getTargetValueByKey(responseBody, orderSeq);}if (StringUtils.isBlank(orderSeq)) {orderSeq getTargetValueByKey(responseBody, order_seq);}if (StringUtils.isBlank(inquiryNo)) {inquiryNo getTargetValueByKey(responseBody, inquiryNo);}if (StringUtils.isBlank(inquiryNo)) {inquiryNo getTargetValueByKey(responseBody, inquiry_no);}if (StringUtils.isBlank(hospCode)) {hospCode getTargetValueByKey(responseBody, hospCode);}if (StringUtils.isBlank(hospCode)) {hospCode getTargetValueByKey(responseBody, hosp_code);}}if (StringUtils.isBlank(systemInteractionLog.getOrgCode())) {systemInteractionLog.setOrgCode(hospCode);}if (StringUtils.isBlank(orderSeq) (StringUtils.isNotBlank(systemInteractionLog.getOrgCode()) StringUtils.isNotBlank(inquiryNo))) {ResultOrderDetailVO result orderApi.queryOrderDetailByInquiryNo(systemInteractionLog.getOrgCode(), inquiryNo);if (Objects.nonNull(result) Objects.nonNull(result.getData())) {OrderDetailVO orderDetailVO result.getData();systemInteractionLog.setPatientId(orderDetailVO.getPatientId());systemInteractionLog.setPatientIdNo(orderDetailVO.getIdCard());systemInteractionLog.setPatientIdType(orderDetailVO.getIdCardType());systemInteractionLog.setUserId(orderDetailVO.getUserId());systemInteractionLog.setHospitalId(orderDetailVO.getHospitalId());systemInteractionLog.setOrgCode(orderDetailVO.getOrgCode());systemInteractionLog.setOrderSeq(orderDetailVO.getOrderSeq());}}try {//补充字段if (StringUtils.isNotBlank(orderSeq)) {systemInteractionLog.setOrderSeq(orderSeq);if (systemInteractionLog.getPath().contains(/reg/occupy)) {Thread.sleep(3000L);}ResultOrderDetailVO result orderApi.queryOrderDetailBySeq(orderSeq);if (Objects.nonNull(result) Objects.nonNull(result.getData())) {OrderDetailVO orderDetailVO result.getData();systemInteractionLog.setPatientId(orderDetailVO.getPatientId());systemInteractionLog.setPatientIdNo(orderDetailVO.getIdCard());systemInteractionLog.setPatientIdType(orderDetailVO.getIdCardType());systemInteractionLog.setUserId(orderDetailVO.getUserId());systemInteractionLog.setHospitalId(orderDetailVO.getHospitalId());systemInteractionLog.setOrgCode(orderDetailVO.getOrgCode());}}} catch (Exception e) {log.warn(错误参数:{}, e.getMessage());}if (StringUtils.isBlank(systemInteractionLog.getOrgCode()) StringUtils.isNotBlank(systemInteractionLogDto.getTenantId())) {ResultHospitalVo result hospitalApi.queryByTenantId(systemInteractionLogDto.getTenantId());if (Objects.nonNull(result) Objects.nonNull(result.getData())) {systemInteractionLog.setHospitalId(result.getData().getHospitalId());systemInteractionLog.setOrgCode(result.getData().getOrgCode());}} else if (StringUtils.isNotBlank(systemInteractionLog.getOrgCode()) systemInteractionLog.getOrgCode().length() 8) {ResultHospitalVo result hospitalApi.queryByOrgCode(systemInteractionLog.getOrgCode());if (Objects.nonNull(result) Objects.nonNull(result.getData())) {systemInteractionLog.setHospitalId(result.getData().getHospitalId());systemInteractionLog.setOrgCode(result.getData().getOrgCode());}}//保存数据到本月对应的表中SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyyMM);String data simpleDateFormat.format(new Date());MonthTableNameHandler.setData(data);// 自增idLong id redisTemplate.opsForValue().increment(ihm_system_interaction_log);systemInteractionLog.setId(id);return save(systemInteractionLog);}
4.3 分表效果