一,业务背景

	业务上要求存储数据的时候根据某个字段动态的选择数据要存储的表.
	如根据code字段: code->[1001,1002]来进行选择存储的表:
	经过下面的配置实现动态表名如 --> table1_1001,table_1002的效果.以此动态生成表名的效果.

二,解决方案

使用mybatis-plus中的动态表名插件,而且版本必须是3.1.2以上版本

需求,将数据按照月份放在不同的表中,2022年1月份数据放在monitor_accelerometer_rapid202201表中,2022年2月份数据放在monitor_accelerometer_rapid202202表中,通常这种需求还伴随定时任务建表需求。

1,准备工作

说明:表是真实存在,且要动态替换的新表必须与实体类表结构一样

@Data
@TableName("monitor_accelerometer_rapid202201")
public class SensorValue implements Serializable {
    private static final long serialVersionUID = 5892027263270309341L;

    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;

    private Integer pointId;

    private Integer equipmentId;

    private String sensorNo;

    @TableField(value = "create_time",fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date sensorTime;

    private String sensorValueJson;
}

2,在mybatis-plus配置的分页插件中添加如下代码

配置好插件后,并不会影响其他分页功能的使用

@Configuration
public class MybatisPlusConfig {

	//分页插件总添加动态表名插件
	@Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // DynamicTableNameParser 表名解析器,动态解析表名,ITableNameHandler 表名处理。
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
        	//metaObject 元对象 ;sql 执行的SQL ;tableName 表名
        	//这里put的key就是需要替换的原始表名,也就是实体类的表名
        	//这里的tableName就是我们定义的动态表名变量,
            put("monitor_accelerometer_rapid202201", (metaObject, sql, tableName) -> {
                // 获取传入参数 tableName,tableName的值就是替换后的表名
                Object param = getParamValue("tableName", metaObject);
                if(param == null){
                    return tableName;//不带tableName参数就返回原表名
                }else {
                    return param.toString();//带tableName参数就返回新表名
                }
            });
        }});
        paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));
        return paginationInterceptor;
    }

	/**
     * 获取动态表tableName参数的值
     */
    private Object getParamValue(String title, MetaObject metaObject){
        //获取参数
        Object originalObject = metaObject.getOriginalObject();
        JSONObject originalObjectJSON = JSON.parseObject(JSON.toJSONString(originalObject));
        JSONObject boundSql = originalObjectJSON.getJSONObject("boundSql");
        try {
            JSONObject parameterObject = boundSql.getJSONObject("parameterObject");
            return parameterObject.get(title);
        }catch (Exception e) {
            return null;
        }
    }
	
	//拆分之后的代码,和上面的方法一样
 	@Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        // 动态表名SQL解析器  DynamicTableNameParser 动态解析表名,ITableNameHandler 表名处理。
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        Map<String,ITableNameHandler> tableNameHandlerMap = new HashMap<>();
        // Map的key就是需要替换的原始表名
        tableNameHandlerMap.put("monitor_accelerometer_rapid202201",new ITableNameHandler(){
            //metaObject 元对象 ;sql 执行的SQL ;tableName 表名
            @Override
            public String dynamicTableName(MetaObject metaObject, String sql, String tableName) {

                // 获取传入参数 tableName,tableName的值就是替换后的表名
                Object param = getParamValue("tableName", metaObject);
                if(param == null){
                    return tableName;//不带tableName参数就返回原表名
                }else {
                    return param.toString();//带tableName参数就返回新表名
                }

            }
        });
        dynamicTableNameParser.setTableNameHandlerMap(tableNameHandlerMap);
        // 创建SQL解析器集合
        List<ISqlParser> sqlParserList = new ArrayList<>();
        sqlParserList.add(dynamicTableNameParser);
        paginationInterceptor.setSqlParserList(sqlParserList);

        return paginationInterceptor;
    }

3,实现代码

控制层

@RequestMapping("/sensorValue")
@RestController
public class SensorValueController {
	 @Autowired
    private SensorValueService sensorValueService;
	
	@RequestMapping("/save")
	public String save(SensorValue sensorValue){
	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
    String time = sdf.format(new Date());
    //动态设置表名
    String tableName = "monitor_accelerometer_rapid"+time;;
	sensorValueService.saveSensorValue(sensorValue,tableName)
	}
}

业务层略
持久层

public interface SensorValueMapper extends BaseMapper<SensorValue> {
    @Insert("INSERT INTO monitor_accelerometer_rapid202201 (point_id,equipment_id,sensor_no,create_time,sensor_time,sensor_value_json) " +
            "VALUES (#{sensorValue.pointId},#{sensorValue.equipmentId},#{sensorValue.sensorNo},#{sensorValue.createTime},#{sensorValue.sensorTime},#{sensorValue.sensorValueJson})")
    boolean saveSensorValue(SensorValue sensorValue, String tableName);
}

结果
这里是新增数据,如果查询数据,在正常查询的基础上多传一个参数tableName。

INSERT INTO monitor_accelerometer_rapid202202  (point_id, equipment_id, sensor_no, create_time, sensor_time, sensor_value_json) VALUES (?, ?, ?, ?, ?, ?) ::: [702, 479, L1_JS_1, null, 2022-02-17 18:30:09.823, {"gX":"0.0","gY":"0.0","gZ":"0.0"}

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐