0

Hibernate 3.3、JPA 1.x、およびHsqldb1.8を使用する

他のオブジェクトのコレクションを含むオブジェクトへのカスケード更新に問題があります。これは、説明するために考案された(わずかに)例です(ゲッター/セッターは省略)。申し訳ありませんが、コードがたくさんあります。問題を表現する別の方法を見つけることができず、すべてがここでかなり簡単です。

@Entity
public class Salesman
{
  @Id
  @GeneratedValue
  @Column(name="salesman_id")
  private long id;

  @OneToMany(mappedBy=salesman, targetEntity=ContactSet.class, fetch=FetchType.EAGER, cascade=CascadeType.All)
  private Set<ContactSet> contacts;
}


@Entity
public class Company
{
  @Id
  @GeneratedValue
  @Column(name="company_id")
  private long id;

  @Column(name="company_name")
  private String name;
}


@Entity
public class ContactSet
{
  @Id
  @GeneratedValue
  @Column(name="contact_set_id")
  private long id;

  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumn(name="salesman_id",referencedColumnName="salesman_id", updatable=false, nullable=false)
  private Salesman salesman

  @ManyToOne
  @JoinColumn(name="company_id", referencedColumnName="company_id", updatable=false, nullable=false)
  private Company company;

  @OneToMany(mappedBy="contactSet", targetEntity=Contact.class, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
  private Set<Contact> contacts;
}


@Entity
public class Contact
{
  @Id
  @GeneratedValue
  @Column(name="contact_id")
  private long id;

  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumn(name="contact_set_id",referencedColumnName="contact_set_id", updatable=true, nullable=false)
  private ContactSet contactSet;

  @Column(name="contact_name", updatable=false, nullable=false)
  private String name;
}

したがって、セールスマンには会社ごとに一連の連絡先があり、会社にサービスを提供するセールスマンが多数いて、それぞれが異なる連絡先を持っている場合があります。新しい会社(および関連する連絡先)をセールスマンに追加できます。すべて問題ありません。

この問題は、すでにいくつかの会社を持っているセールスマンに新しい会社(および連絡先)を追加するときに発生します。

session.beginTransaction();
session.lock(salesman, LockMode.NONE)
ContactSet newSet = new ContactSet();
/*...Add contacts to ContactSet...*/
salesman.addContactSet(newSet);
session.saveOrUpdate(salesman);
session.commit();

これをhibernate.show_sql=trueで実行すると、各連絡先に対して挿入を実行し、新しい連絡先セットに対して挿入を実行するという期待される効果があることがわかります。また、セールスマン自体の更新と、問題のセールスマンが持っている他のすべてのContactSetおよびContactの更新も表示されます。セールスマンごとに数千の連絡先があるため、このトランザクションには長い時間がかかります。

私の質問は、変更されていないことがわかっているContactSetsとContactsのすべての更新を回避するにはどうすればよいですか?@Versionタグを追加し、CascadeTypeを変更して(私のアプリケーションではALL以外はすべて失敗します)、より具体的なコードをいじくり回してみましたが、成功しませんでした。

ポインタを事前に感謝します、

**編集:session.lock(salesman、LockMode.NONE)をトランザクションに追加すると、他のオブジェクトは更新されませんが、コードはまだ低速であることがわかりました。まだ何千ものオブジェクトをセッションに追加してそれらをロックしているので、私は疑っています。これを反映するようにサンプルコードを更新しました。LockMode.NONEは、切り離されたオブジェクトをセッションに再関連付けするだけです。

フィル

4

1 に答える 1

0

これに対する適切な解決策を見つけることができなかったため、ContactSetを会社とSalesmanに保存し、Salesman->ContactSetからすべてのカスケードを削除することになりました。これで、新しい会社を保存するだけで、すべての新しいContactSetが保存されます。すべてのセールスマンのContactSetを更新する必要がある状況はまだあります。これは、すべてのセールスマンの会社を保存することによってのみ解決できます(私が見る限り)。

誰かがより良い解決策を見つけたら、追加してください!

于 2012-11-16T15:14:56.450 に答える