0

次のことを考慮してください。

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

シナリオ:

  1. community1はuser1に割り当てられます(データベースに挿入されます)
  2. community2はuser1に割り当てられます(データベースに挿入されます)
  3. community1はuser2に割り当てられています(データベースに挿入されています)
  4. community2はuser2に割り当てられています(データベースに挿入されていない、throws NonUniqueObjectException
  5. 私がtemplate.merge(user)代わりに使用する場合template.saveOrUpdate(user)..それは動作します..なぜ???
4

1 に答える 1

0

saveOrUpdate()切り離されたオブジェクトをupdate()取得し、このオブジェクト インスタンスをセッションにアタッチします。したがって、同じタイプと ID を持つエンティティがすでにセッションにアタッチされている場合、Hibernate は別のインスタンスをアタッチできません。セッションに特定の ID を持つエンティティが 1 つだけ存在するという保証が破られます。したがって、この例外がスローされます。

merge()異なります。切り離されたエンティティを取得し、まだロードされていない場合はセッションで同じ ID を持つエンティティをロードし、切り離されたエンティティの状態 (つまり、フィールド) を添付されたエンティティにコピーします。切り離されたエンティティは、切り離されたまま変更されません。

したがって、一般的にmerge()は、優先する必要があります。ところで、他のメソッドは JPA API には存在しません。saveOrUpdate() を使用する場合は、NonUniqueException が発生する状況にならないように、通常はトランザクションの最初の命令として呼び出す必要があります。

于 2012-12-31T15:48:39.700 に答える