java – 用mybatis保存/更新集合,常见的做法是什么?

前端之家收集整理的这篇文章主要介绍了java – 用mybatis保存/更新集合,常见的做法是什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我决定尝试使用mybatis进行一个新项目.我非常熟悉sql,而且我最近对hibernate有一些不好的经历,所以我正在寻找一个更低级别的DAO方法.

似乎相当不错,除了一件事,那就是处理集合.@H_404_3@

我有两个POJO,组和用户,它们是多对多的.我已经决定了一个设计理念,一个拥有集合的POJO只能在保存时更新表之间的M-M关系.因此,例如,当我保存具有用户集合的组对象时,设计原理决定了用户应该已经被保存,并且我只需要在数据库中保存组和group_user关系.@H_404_3@

所以,对于接口中的saveGroup函数,我为mybatis做了这个XML映射:@H_404_3@

<insert id="saveGroup" keyColumn="id"
    parameterType="se.myapp.domain.Group">
    <choose>
        <when test="id == null">
        INSERT INTO myapp_group (name,description)
        VALUES
        (#{username},#{password});
        </when>
        <otherwise>
        UPDATE myapp_group set name=#{name},description=#{description}
        where id=#{id};
        </otherwise>
    </choose>

    <if test="users != null">
        create temporary table tmpnewgroups (group_id integer,user_id integer);

        insert into tmpnewgroups (group_id,user_id) values (
        <foreach collection="users" item="user" open="" close="" separator="),()">
             #{id},#{user.id}
        </foreach>
        );

        insert into myapp_user_group(group_id,user_id) 
        select tmp.group_id,tmp.user_id 
        from tmpnewgroups tmp 
        left outer join myapp_user_group ug 
            on ug.group_id = tmp.group_id and ug.user_id = tmp.user_id
        where ug.group_id is null;

        delete from myapp_user_group 
        where group_id = #{id} and user_id not in (select user_id from tmpnewgroups);
    </if>

</insert>

这将按照预期的方式工作(插入/更新组,将用户的集合保存为数据库中的关系).但是我并不觉得这是最好的做法.应用程序是为了使我可以切换到休眠状态,如果需要,所以最好保存收集的逻辑应该在数据库层.在mybatis有没有一些“魔法”,我不知道可以简化这样的操作吗?@H_404_3@

有什么想法如何改善这个?或者我应该重新思考应用程序设计,并将集合的处理进一步放在模型中?@H_404_3@

解决方法

您的saveGroup数据映射操作的第二部分确实是重新思考您的应用程序设计的一个原因.将内存中的用户集合持久化到临时表以将其与持久化的用户对象进行比较,以便插入和删除三角形是一个相当繁重的操作,如果只需要更新组的名称或描述,则根本不需要,即当没有三角洲时.这种情况是否可以由数据库服务器(您当前的解决方案)或数据库客户端(您的应用程序)决定.

除了组和可能的用户需要首次插入的情况外,如果希望应用程序决定是否需要更新链接表,那么您的应用程序需要知道用户集合是否已更改,因为它从数据库中检索.不幸的是,MyBatis不会帮助你的应用程序.@H_404_3@

看到,与Hibernate相比,MyBatis在MyBatis完成工作后幸免地不了解你的对象和他们携带的状态,这是数据映射,而不是对象关系映射. Hibernate可以自动检测所谓的脏状态的对象,MyBatis不能,因为这不是其作业描述的一部分.所以你会留给自己的设备.@H_404_3@

一个超简单的方法是在选择之后存储用户的哈希码,并检查该哈希码是否使用称为isUserDirty()的方法进行更改.您可以使用< if test =“isUserDirty”>从映射中简单地测试该条件.这当然不是一个非常通用的方法,而是依赖于一个体面的hashCode()实现.看一下leonbloy的answer类似的一个更通用的方法的问题.当然这可能还是太简单了,特别是因为我们谈论了很多关系.哪种方法最好取决于你的情况.@H_404_3@

现在你应该知道该怎么做祝你好运!@H_404_3@

PS而不是插入和删除增量我会建议一个简单的覆盖:删除所有然后插入所有在一个事务.您的临时表策略是一个优化策略,实际上可能实际上不会提高数据库性能,实际上我的猜测是可能会更糟.如果您对此策略进行了正确的分析,并且知道您正在做什么,您可能会忽略此后记.@H_404_3@

猜你在找的Java相关文章