關於雪花ID自動生成和Tk.mybatis的問題
阿新 • • 發佈:2020-12-17
考慮到公司後期可能會出現分庫的情況,所以準備改動一下表資料,把主鍵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=\"@[email protected](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")
即可。