Mybatis在执行批量插入时,如果使用的是for循环逐一插入,那么可以正确返回主键id。如果使用动态sql的foreach循环,那么返回的主键id列表,可能为null,这让很多人感到困惑;本文将分析问题产生的原因,并修复返回主键id为null的问题。该问题在开源中国社区,以及网络上,已经有很多人遇到并发帖咨询,似乎都没有得到期望的解决结果。今天,我将带领大家,分析并解决该问题,让foreach批量插入,返回正确的id列表。
<insert id="insertStudents" useGeneratedKeys="true" keyProperty="studId"
parameterType="java.util.ArrayList"> INSERT INTO STUDENTS(STUD_ID, NAME, EMAIL,
DOB, PHONE) VALUES<foreach collection="list" item="item" index="index" separator
=","> (#{item.studId},#{item.name},#{item.email},#{item.dob}, #{item.phone}) </
foreach> </insert>
以上便是Mybatis的foreach循环,其要生成的sql语句是:insert into students(stud_id, name)
values(?, ?),(?, ?), (?, ?); 类似这样的批量插入。

Mybatis是对Jdbc的封装,我们来看看,Jdbc是否支持上述形式的批量插入,并返回主键id列表的。
PreparedStatement pstm = conn.prepareStatement("insert into students(name,
email) values(?, ?), (?, ?), (?, ?)", Statement.RETURN_GENERATED_KEYS);
pstm.setString(1, "name1"); pstm.setString(2, "email1"); pstm.setString(3,
"name2"); pstm.setString(4, "email2"); pstm.setString(5, "name2");
pstm.setString(6, "email2"); pstm.addBatch(); pstm.executeBatch(); ResultSet rs
= pstm.getGeneratedKeys();while (rs.next()) { Object value = rs.getObject(1);
System.out.println(value); }
Output:
248 249 250
好了,事实证明,Jdbc是支持上述批量插入,并能正确返回id列表的。Jdbc都支持,如果Mybatis却不支持,有点说不过去。

1. Mapper.xml中keyProperty和parameterType属性之间的关系(很重要)
useGeneratedKeys="true" keyProperty="studId" parameterType="Student"
上述xml配置,含义为,属性studId是参数类型Student对象的主键属性。毫无疑问,Student对象中有studId属性。
useGeneratedKeys="true" keyProperty="studId" parameterType=
"java.util.ArrayList"
那这个如何解释呢?ArrayList有studId属性吗?当然没有了。其正确含义为:ArrayList集合中的元素的studId属性。

所以,keyProperty和parameterType之间的关系,有时是直接关系,有时是间接关系。明白这个道理之后,我们就可以开始进一步阅读源码了。


详情:参考https://my.oschina.net/zudajun/blog/674946,http://www.cnblogs.com/admol/articles/4248159.html
<> <!-- 批量插入生成的兑换码 --> 2 <insert id ="insertCodeBatch"
parameterType="java.util.List" > 3 <selectKey resultType ="java.lang.Integer"
keyProperty= "id" 4 order= "AFTER"> 5 SELECT LAST_INSERT_ID() 6 </selectKey > 7
insert into redeem_code 8 (bach_id, code, type,
facevalue,create_user,create_time) 9 values 10 <foreach collection ="list"
item="reddemCode" index= "index" separator =","> 11 ( 12 #{reddemCode.batchId},
#{reddemCode.code}, 13 #{reddemCode.type}, 14 #{reddemCode.facevalue}, 15
#{reddemCode.createUser}, #{reddemCode.createTime} 16 ) 17 </foreach > 18
</insert > 示例: <> 向orderitem里面批量插入数据 <insert id="addOrderitem"
useGeneratedKeys="true" keyProperty="oid"
        parameterType="java.util.ArrayList">
    
        insert into orderitem(iid,count,subtotal,oid,bid)
        values
        <foreach collection="list" item="item" index="index"
            separator=",">
            (#{item.iid},#{item.count},#{item.subtotal},#{item.orders.oid},
            #{item.bid})
        </foreach>
    </insert> 写成#{item.orders.oid}的原因如下 public class orderitem {
    private int iid;
    private int count;
    private double subtotal;
    private orders orders;
    private book book;
    /**}
public class orders {
    private int oid;
    private Date ordertime;
    private double total;
    private int state;
    private int uid;
    private user owner;
    private List<orderitem> orderitem; ---
    }

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信