批量插入并获取生成的密钥时,获取错误。 批量插入工作正常。
对象结构:
对象1:
Long id, String name, Obj2 obj
对象2:(Obj2)
Long id, String value
两个对象都存储在不同的表中。
表 object1
id | name | object2_id (Foreign Key)
表 object2
id | value
现在我有一个对象1 列表要插入。
该过程将插入对象2 获取ID,并将对象1 插入 Object2的 id (作为外键)。
插入 Object2 时,Mapper.xml中的插入块
案例1:
<insert id="batchInsert" parameterType="list" useGeneratedKeys="true" keyProperty="obj1s.obj2.id">
<!-- obj1s is name of the list -->
insert into object2 (value) values
<foreach collection="obj1s" item="obj1" separator=",">
(#{obj1.obj2.id})
</foreach>
</insert>
错误:获取生成密钥或将结果设置为参数对象时出错。
案例2:
<insert id="batchInsert" parameterType="list" useGeneratedKeys="true" keyProperty="obj1.obj2.id">
<!-- obj1 so as to access the object of foreach loop -->
insert into object2 (value) values
<foreach collection="obj1s" item="obj1" separator=",">
(#{obj1.obj2.id})
</foreach>
</insert>
错误:获取生成密钥或将结果设置为参数对象时出错。原因:org.apache.ibatis.binding.BindingException:找不到参数'obj1'。可用参数是[obj1s,param1]
案例3:
<insert id="batchInsert" parameterType="list" useGeneratedKeys="true" keyProperty="obj2.id">
<!-- obj2 is the object with variable id to store generated key -->
insert into object2 (value) values
<foreach collection="obj1s" item="obj1" separator=",">
(#{obj1.obj2.id})
</foreach>
</insert>
错误:获取生成密钥或将结果设置为参数对象时出错。原因:org.apache.ibatis.binding.BindingException:找不到参数'obj2'。可用参数是[obj1s,param1]
反正有没有实现这个目标? 可能使用 selectKey ,但selectkey用于不支持自动生成密钥的DB。
使用MyBatis 3.3.1和Mysql。
答案 0 :(得分:10)
所以,我明白了。 MyBatis存在多行插入和useGenerated密钥的错误。在进行批量插入和获取生成密钥时,Bug是列表变量名称必须是&#34; list&#34; 。然后相应地访问该对象。因此,对于上面的示例,代码将如下所示:
<insert id="batchInsert" parameterType="list" useGeneratedKeys="true" keyProperty="obj2.id">
<!-- obj2 is the object with variable id to store generated key -->
insert into object2 (value) values
<foreach collection="list" item="obj1" separator=",">
(#{obj1.obj2.id})
</foreach>
并且mapper.java方法声明将如下所示:
public Integer batchInsert(@Param("list")List<Obj1> obj1);
变量名称必须为列表。没别了。
感谢@blackwizard,我重新审视并检查了这个错误,让我得到了这个答案。
答案 1 :(得分:0)
您必须访问obj.id
, obj 是属性名称, Obj2 是类型名称。
此外,检索生成的键有效/仅对单个插入有意义。 确实:您想插入N条记录,但您的代码将生成并执行单个(巨型)语句。这不是批处理。
在Java中迭代你的列表,在循环中调用更简单的insert语句(不再是foreach),然后每个生成的键都可以绑定到匹配的对象。 使用ExecutorType.REUSE打开SqlSession,这样语句只准备一次,每次迭代都只发送参数。
我已经回答this kind of question。