mybatis-sqlserver批量新增返回id方式

 更新时间:2024年05月18日 09:51:52   作者:rong0016  
这篇文章主要介绍了mybatis-sqlserver批量新增返回id方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

遇到的问题

公司最近接到项目需要使用SqlServer,在做SQL兼容的时候遇到问题,批量新增数据时只返回的第一条记录的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.发现上述步骤的Jdbc3KeyGenerator是有接口的KeyGenerator,查看后发现有3个实现类了解到SelectKeyGenerator通过selectKeyt标签可以返回id;

3.查看SelectKeyGenerator源码了解到只支持返回单个id;

4.通过百度了解到SqlServer通过output inserted.id可以输出id;

5.是否可以自己实现KeyGenerator来解决批量返回id的方法呢?

6.最后我没找到配置自定义的实现类的方式,决定通过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 {
       // 正常执行代码 获取返回结构集
       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();
           // 处理入参对象
           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"))));
           }
           // 返回假数据防止异常
           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对象参数必须放在第一位,拦截器的代码写的比较粗糙,给各位提供思路。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java工具类StringUtils使用实例详解

    java工具类StringUtils使用实例详解

    这篇文章主要为大家介绍了java工具类StringUtils使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Java的long和bigint长度对比详解

    Java的long和bigint长度对比详解

    在本文中小编给大家分享了关于Java的long和bigint长度比较的知识点内容,有兴趣的朋友们学习参考下。
    2019-07-07
  • Java数据结构之AC自动机算法的实现

    Java数据结构之AC自动机算法的实现

    AC自动机算法常被认为是Trie树+KMP算法的结合体,它是一个多模式匹配算法,在模式匹配领域被广泛应用。本文将详细为大家介绍AC自动机的原理与实现方法,感兴趣的可以了解一下
    2022-12-12
  • Java实现将容器 Map中的内容保存到数组

    Java实现将容器 Map中的内容保存到数组

    这篇文章主要介绍了Java实现将容器 Map中的内容保存到数组,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java编程简单应用

    Java编程简单应用

    本文主要介绍了三个简单Java小程序———1、HelloWorld(HelloWorld的来源);2、输出个人信息3、输出特殊图案。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • JDK20 + SpringBoot 3.1.0 + JdbcTemplate 使用案例详解

    JDK20 + SpringBoot 3.1.0 + JdbcTemplate 使用案例详解

    通过 JdbcTemplate 直接执行 SQL 语句,结合源码动态编译即可方便实现动态修改代码逻辑的效果,这篇文章主要介绍了JDK20 + SpringBoot 3.1.0 + JdbcTemplate 使用,需要的朋友可以参考下
    2023-09-09
  • JDBC如何通过SSL方式连接MySQL

    JDBC如何通过SSL方式连接MySQL

    文章介绍了如何配置MySQL以支持SSL连接,并通过JDBC进行安全连接,主要内容包括查看MySQL SSL支持、创建SSL连接用户、配置用户是否强制使用SSL、JDBC配置导入证书以及使用Go编写一个简单的HTTP文件服务器来提供SSL证书
    2025-02-02
  • 详解spring与shiro集成

    详解spring与shiro集成

    这篇文章主要介绍了详解spring与shiro集成,需要的朋友可以参考下
    2017-09-09
  • SpringCloud Gateway动态转发后端服务实现过程讲解

    SpringCloud Gateway动态转发后端服务实现过程讲解

    这篇文章主要介绍了SpringCloud Gateway动态转发后端服务实现过程,简单的路由转发可以通过SpringCloudGateway的配置文件实现,在一些业务场景种,会需要动态替换路由配置中的后端服务地址,单纯靠配置文件无法满足这种需求
    2023-03-03
  • Java中Thread类详解及常用的方法

    Java中Thread类详解及常用的方法

    在java中谈到线程,必然少不了Thread类,下面这篇文章主要给大家介绍了关于Java中Thread类及常用的方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-05-05

最新评论