前言
系统升级后,原来的数据库结构及业务逻辑发生了变化,升级后的系统需要兼容历史数据,此时就需要对历史数据进行清洗。历史数据的清洗方式可以分为两种:
使用SQL脚本开发清洗逻辑
使用Java开发清洗逻辑,通过接口执行
通常,产品化的应用系统在做升级处理时,都是选择SQL脚本的方式进行清洗数据的。
企业内部,对于线上运行的项目,使用SQL脚本对数据进行变更都需要经过工单系统,流程相对复杂。此时将清洗逻辑直接使用编码的方式在系统中实现是相对比较简单的。
使用MyBatis
在使用MyBatis做数据清洗时,遇到了一个问题,那就是清洗后的数据无法指定主键即id的值,新写入的数据主键值被数据自增ID替换掉了。
/**
* 自增主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
问题就出现在@TableId
注解上。
@TableId是MyBatis-Plus提供的注解,@TableId注解代码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableId {
/**
* <p>
* 字段值(驼峰命名方式,该值可无)
* </p>
*/
String value() default "";
/**
* <p>
* 主键ID
* </p>
* {@link IdType}
*/
IdType type() default IdType.NONE;
}
可以看到IdType
是用来表示主键的创建方式的。
public enum IdType {
AUTO(0, "数据库ID自增"), INPUT(1, "用户输入ID"),
/* 以下2种类型、只有当插入对象ID 为空,才自动填充。*/
ID_WORKER(2, "全局唯一ID"), UUID(3, "全局唯一ID"), NONE(4, "该类型为未设置主键类型"),
ID_WORKER_STR(5, "字符串全局唯一ID");
...
}
在IdType
中定义了多种id生成方式。可以看AUTO
的创建方式是使用数据库ID自增,此时在执行插入操作时,MyBatis-Plus会对实体模型中的id字段清除掉,再执行插入。INPUT
方式在实行插入时候,不会对ID主键进行处理,如果用户设置了ID,将会把该值直接插入。
所以在使用编码方式对数据进行清洗时,还需要修改模型的ID上的@TableId
为@TableId(value = "id", type = IdType.AUTO)
总结
不同的洗数方案,都有各自的优势,在选择方案时,还需要结合外部的环境进行全面考虑。