mybatis-sqlserver批量新增返回id方式
遇到的問題
公司最近接到項目需要使用SqlServer,在做SQL兼容的時候遇到問題,批量新增數(shù)據(jù)時只返回的第一條記錄的id
解決思路
1.參考mysql
<insert id="batchInsert" userGeneratedKeys="true" keyProperty="id">
insert into public_user (name,password)
values
<foreach collection="list" separator="," item="item">
(#{item.name}, #{itme.password})
</foreach>
</insert>具體mybatis封裝id的地方在org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator
主要邏輯是通過Statement.getGeneratedKeys()獲取id結果集.
SqlServer只能獲取第一個
2.發(fā)現(xiàn)上述步驟的Jdbc3KeyGenerator是有接口的KeyGenerator,查看后發(fā)現(xiàn)有3個實現(xiàn)類了解到SelectKeyGenerator通過selectKeyt標簽可以返回id;
3.查看SelectKeyGenerator源碼了解到只支持返回單個id;

4.通過百度了解到SqlServer通過output inserted.id可以輸出id;
5.是否可以自己實現(xiàn)KeyGenerator來解決批量返回id的方法呢?
6.最后我沒找到配置自定義的實現(xiàn)類的方式,決定通過mybatis的攔截器解決
代碼
mybatis攔截器
@Component
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}))
public class SqlServerKeyGeneratorInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 正常執(zhí)行代碼 獲取返回結構集
List<Object> values = (List)invocation.proceed();
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
// 判斷是否selectKey查詢語句
if (ms.getId().endsWith(SelectKeyGenerator.SELECT_KEY_SUFFIX)) {
Configuration configuration = ms.getConfiguration();
// 處理入?yún)ο?
Collection<Object> parameters = getParameters(invocation.getArgs()[1]);
// 封裝id
for (int i = 0; i < parameters.size(); i++) {
MetaObject metaObject = configuration.newMetaObject(parameters.toArray()[i]);
metaObject.setValue("id", Long.valueOf((Integer)(((Map)values.get(i)).get("id"))));
}
// 返回假數(shù)據(jù)防止異常
List<Long> ids = new ArrayList<>();
ids.add(1L);
return ids;
}
return values;
}
@Override
public Object plugin(Object target) {
return null;
}
@Override
public void setProperties(Properties properties) {
}
/** 來源 Jdbc3KeyGenerator */
private Collection<Object> getParameters(Object parameter) {
Collection<Object> parameters = null;
if (parameter instanceof Collection) {
parameters = (Collection) parameter;
} else if (parameter instanceof Map) {
Map parameterMap = (Map) parameter;
if (parameterMap.containsKey("collection")) {
parameters = (Collection) parameterMap.get("collection");
} else if (parameterMap.containsKey("list")) {
parameters = (List) parameterMap.get("list");
} else if (parameterMap.containsKey("array")) {
parameters = Arrays.asList((Object[]) parameterMap.get("array"));
}
}
if (parameters == null) {
parameters = new ArrayList<Object>();
parameters.add(parameter);
}
return parameters;
}
}
mapper
<insert id="batchInsert">
<selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="java.util.Map">
insert into public_user (name,password)
output inserted.id
values
<foreach collection="list" separator="," item="item">
(#{item.name}, #{itme.password})
</foreach>
<selectKey>
</insert>
PS:
需要注意的是id對象參數(shù)必須放在第一位,攔截器的代碼寫的比較粗糙,給各位提供思路。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用Java將Excel轉換為Text的實現(xiàn)方法
在日常的數(shù)據(jù)處理和系統(tǒng)集成中,我們經(jīng)常會遇到需要將Excel文件中的數(shù)據(jù)提取出來,并以純文本格式進行處理的場景,將Excel轉換為Text是一項基礎而重要的任務,本文將向您介紹如何利用強大的 Spire.XLS for Java 庫,在Java應用程序中輕松實現(xiàn)Excel到Text的轉換2025-10-10
JavaEE的進程,線程和創(chuàng)建線程的5種方式詳解
這篇文章主要為大家詳細介紹了JavaEE的進程,線程和創(chuàng)建線程的5種方式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
SpringBoot兩種方式接入DeepSeek的實現(xiàn)
本文主要介紹了SpringBoot兩種方式接入DeepSeek的實現(xiàn),包括HttpClient方式和基于spring-ai-openai的方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-03-03
基于ElasticSearch Analyzer的使用規(guī)則詳解
這篇文章主要介紹了基于ElasticSearch Analyzer的使用規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

