似乎相当不错,除了一件事,那就是处理集合.
我有两个POJO,组和用户,它们是多对多的.我已经决定了一个设计理念,一个拥有集合的POJO只能在保存时更新表之间的M-M关系.因此,例如,当我保存具有用户集合的组对象时,设计原理决定了用户应该已经被保存,并且我只需要在数据库中保存组和group_user关系.
所以,对于接口中的saveGroup函数,我为mybatis做了这个XML映射:
<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有没有一些“魔法”,我不知道可以简化这样的操作吗?
有什么想法如何改善这个?或者我应该重新思考应用程序设计,并将集合的处理进一步放在模型中?
解决方法
除了组和可能的用户需要首次插入的情况外,如果希望应用程序决定是否需要更新链接表,那么您的应用程序需要知道用户集合是否已更改,因为它从数据库中检索.不幸的是,MyBatis不会帮助你的应用程序.
看到,与Hibernate相比,MyBatis在MyBatis完成工作后幸免地不了解你的对象和他们携带的状态,这是数据映射,而不是对象关系映射. Hibernate可以自动检测所谓的脏状态的对象,MyBatis不能,因为这不是其作业描述的一部分.所以你会留给自己的设备.
一个超简单的方法是在选择之后存储用户的哈希码,并检查该哈希码是否使用称为isUserDirty()的方法进行更改.您可以使用< if test =“isUserDirty”>从映射中简单地测试该条件.这当然不是一个非常通用的方法,而是依赖于一个体面的hashCode()实现.看一下leonbloy的answer类似的一个更通用的方法的问题.当然这可能还是太简单了,特别是因为我们谈论了很多关系.哪种方法最好取决于你的情况.
现在你应该知道该怎么做祝你好运!
PS而不是插入和删除增量我会建议一个简单的覆盖:删除所有然后插入所有在一个事务.您的临时表策略是一个优化策略,实际上可能实际上不会提高数据库的性能,实际上我的猜测是可能会更糟.如果您对此策略进行了正确的分析,并且知道您正在做什么,您可能会忽略此后记.