MyBatis useGeneratedKeys 批量插入嵌套对象

MyBatis useGeneratedKeys for nested object in batch insert

批量插入和获取生成的key时,报错。 批量插入工作正常。

对象结构:

对象 1:

Long id, String name, Obj2 obj 

对象 2:(Obj2)

Long id, String value

两个对象都存储在不同的表中。

Table object1

id | name  | object2_id (Foreign Key)

Table object2

id | value

现在我有一个要插入的 对象 1 的列表。

进程会insert Object 2获取id,insert Object 1 with " id " of Object2(作为外键)。

在插入Object2时,插入块在Mapper.xml

案例一:

<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>

ERROR: Error getting generated key or setting result to parameter object.

案例二:

<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>

ERROR: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.binding.BindingException: Parameter 'obj1' not found. Available parameters are [obj1s, param1]

案例三:

<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>

ERROR: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.binding.BindingException: Parameter 'obj2' not found. Available parameters are [obj1s, param1]

有什么办法可以实现吗? 可能使用 selectKey,但 selectkey 用于不支持自动生成密钥的数据库。

使用 MyBatis 3.3.1 和 Mysql。

您必须访问obj.idobj是属性名称,Obj2是类型名称。

此外,检索生成的密钥 works/makes 仅适用于单个插入。 确实:您想插入 N 条记录,但您的代码将生成并执行单个(巨大的)语句。这不是批处理。

遍历 Java 中的列表,在循环中调用更简单的插入语句(不再有 foreach),然后每个生成的键都可以绑定到匹配的对象。 使用 ExecutorType.REUSE 打开 SqlSession,这样语句只准备一次,每次迭代只发送参数。

我已经回答了this kind of question

所以,我想通了。 multi-row 插入和使用生成的密钥时,MyBatis 存在这个错误。 Bug 是列表变量名称 必须是 "list" 进行批量插入并获取生成的密钥时。然后相应地访问对象。所以对于上面的示例,代码将如下所示:

<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);

变量名必须是list。没有别的。

感谢@blackwizard,我重新审视并检查了这个错误,这让我找到了这个答案。