mybatis-sqlserver批量新增返回id

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只能获取第一个

  1. 发现上述步骤的Jdbc3KeyGenerator是有接口的KeyGenerator,查看后发现有3个实现类了解到SelectKeyGenerator通过selectKeyt标签可以返回id;
  2. 查看SelectKeyGenerator源码了解到只支持返回单个id;
    在这里插入图片描述
  3. 通过百度了解到SqlServer通过output inserted.id可以输出id;
  4. 是否可以自己实现KeyGenerator来解决批量返回id的方法呢?
  5. 最后我没找到配置自定义的实现类的方式,决定通过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对象参数必须放在第一位,拦截器的代码写的比较粗糙,给各位提供思路.有更好方案的可以留言.

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值