考虑到公司后期可能会出现分库的情况,所以准备改动一下表数据,把主键ID改为使用雪花ID。关于雪花ID这里不多解读
为了方便,这边做了拦截,所有插入操作且标记了自定义注解的字段,均使用雪花ID生成主键
拦截器的代码比较多,这里就不贴出来了。主要记录一个问题,因为使用的是tk.mybatis。
通常批量插入时,使用通用mapper的insertList方法,也就是包tk.mybatis.mapper.common.special
下的
@RegisterMapper
public interface InsertListMapper<T> {
@Options(
useGeneratedKeys = true
)
@InsertProvider(
type = SpecialProvider.class,
method = "dynamicSQL"
)
int insertList(List<? extends T> var1);
}
问题出在拦截器生成的雪花ID无效,因为在SpecialProvider当中,
拼接sql时跳过了主键。
所以需要自定义一个Provider,提供insertListByCustom方法
public class CustomAddProvider extends MapperTemplate {
public CustomAddProvider (Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
/**
* @Title: insertListByCustom
* @Description:批量添加方法
*/
public String insertListByCustom(MappedStatement ms){
Class<?> entityClass = getEntityClass(ms);
//开始拼sql
StringBuilder sql = new StringBuilder();
sql.append("<bind name=\"listNotEmptyCheck\" value=\"@tk.mybatis.mapper.util.OGNL@notEmptyCollectionCheck(list, '" + ms.getId() + " 方法参数为空')\"/>");
sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass), "list[0]"));
sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" index=\"index\">");
sql.append("<if test=\"index == 0\">");
sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
//获取全部列
Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
for (EntityColumn column : columnList) {
if (column.isInsertable()) {
sql.append(SqlHelper.getIfNotNull("record", column, column.getColumn()+",", isNotEmpty()));
}
}
sql.append("</trim>");
sql.append("</if>");
sql.append("</foreach>");
sql.append(" VALUES ");
sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
for (EntityColumn column : columnList) {
if (column.isInsertable()) {
sql.append(SqlHelper.getIfNotNull("record", column, column.getColumnHolder("record")+",", isNotEmpty()));
}
}
sql.append("</trim>");
sql.append("</foreach>");
return sql.toString();
}
}
使用时和InsertListMapper一样,自定义一个:
@RegisterMapper
public interface CustomBatchAddMapper<T> {
/**
* @Title: insertListByCustom
* @Description:批量插入方法
*/
@Options(keyProperty = "id")
@InsertProvider(type = CustomAddProvider.class, method = "insertListByCustom")
int insertListByCustom(List<T> recordList);
}
注意,这里的@Options不能使用
@Options( useGeneratedKeys = true )
而是:@Options(keyProperty = "id")
否则会出现插入成功后回显ID时不正确,会出现雪花Id自增。例如,我批量插入5条数据,假设拦截器生成的主键ID是(假设):0001,0002,0003,0004,0005,那么正确的返回结果应该也是这样。
但是实际上会返回0005,0006,0007,0008,0009.
@Options( useGeneratedKeys = true )
改成:@Options(keyProperty = "id")
即可。