0

考虑以下:

用户.java

class User{
    ...
    private Set<Community> communities = new HashSet<Community>();
    ...
}

社区.java

class Community{
    ...
    private Set<User> users = new HashSet<User>();
    ...
}

用户.hbm.xml

<set name="communities" cascade="save-update" lazy="false" table="tbl_user_community">
        <key column="user_id" />
        <many-to-many class="Community" column="community_id"/>
     </set> 

社区.hbm.xml

<set name="users" lazy="false" cascade="save-update" table="tbl_user_community" inverse="true">
    <key column="community_id" />
    <many-to-many class="User" column="user_id"/>
</set>

两者都有many-to-many关系。

为用户添加社区的代码:

HibernateTemplate template = null;
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
template = new HibernateTemplate(sessionFactory);

User user = template.get(User.class, "100");
Community community = template.get(Community.class,1);



user.getCommunities().add(community);


template.saveOrUpdate(user);

设想:

  1. community1 分配给 user1(插入数据库)
  2. community2 分配给 user1(插入数据库)
  3. community1 分配给 user2(插入数据库)
  4. community2 分配给 user2 (未插入数据库,抛出NonUniqueObjectException
  5. 如果我使用template.merge(user)而不是template.saveOrUpdate(user)..它可以工作..为什么???
4

1 回答 1

0

saveOrUpdate()update()获取一个分离的对象并将此对象实例附加到会话。因此,如果一个具有相同类型和 ID 的实体已经附加到会话,Hibernate 不能附加另一个实例:它会破坏会话中只有一个具有给定 ID 的实体的保证。所以它抛出了这个异常。

merge()是不同的。它需要一个分离的实体,如果尚未加载,则在会话中加载具有相同 ID 的实体,并将分离实体的状态(即字段)复制到附加实体。分离的实体保持分离和未修改。

所以,一般来说,merge()应该是首选。顺便说一句,JPA API 中不存在其他方法。如果使用 saveOrUpdate(),一般应将其作为事务的第一条指令调用,以避免陷入导致 NonUniqueException 的情况。

于 2012-12-31T15:48:39.700 回答