请考虑以下事项:
User.java
class User{
...
private Set<Community> communities = new HashSet<Community>();
...
}
Community.java
class Community{
...
private Set<User> users = new HashSet<User>();
...
}
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>
Community.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);
情景:
- community1被分配给user1(插入数据库)
- community2被分配给user1(插入数据库)
- community1被分配给user2(插入数据库)
- community2被分配给user2(未插入数据库,抛出
NonUniqueObjectException
)- 如果我使用
醇>template.merge(user)
而不是template.saveOrUpdate(user)
..它有效..为什么???
答案 0 :(得分:0)
saveOrUpdate()
和update()
获取一个分离的对象并将此对象实例附加到会话中。因此,如果具有相同类型和ID的实体已附加到会话,则Hibernate无法附加另一个实例:它将破坏在会话中仅存在具有给定ID的一个实体的保证。所以它抛出了这个例外。
merge()
不同。它需要一个分离的实体,如果尚未加载,则在会话中加载具有相同ID的实体,并将分离的实体的状态(即字段)复制到附加的实体。分离的实体保持未经修改和未修改。
因此,一般来说,merge()
应该是首选。顺便说一下,JPA API中不存在其他方法。如果使用saveOrUpdate(),通常应将其称为事务的第一条指令,以避免出现导致NonUniqueException的情况。