2009-08-06 10 views
1

私の状況は次のとおりです。双方向親子関係を含むオブジェクトをデータベースにロードします。その後、そのオブジェクトがUIにロードされ、子セットから任意の数の子を削除するなど、変更を行うことができます。この変更されたオブジェクトのコピーは、saveOrUpdateメソッドを使用してロードされます。ただし、この変更されたコピーが保存されると、削除された子がデータベースに残ります(新しい子がセットに追加されます)。このプロセスではエラーは発生しませんが、削除された子プロセスを実際にデータベースから削除する必要があります。私は以下の私の休止状態とjavaコードの関連部分を貼り付けました。休止設定Hibernateはデータベースから子を取り除くことができません

<bag name="specimenTypes" table="masterPkSpecimenType" cascade="all-delete-orphan" inverse="true"> 
    <key column="runid"/> 
    <one-to-many class="SpecimenType"/> 
</bag> 

子供:

<many-to-one name="reportCriteriaBean" class="ReportCriteriaBean" column="runid" not-null="true" /> 

親オブジェクトコード:

public List<SpecimenType> getSpecimenTypes() { 
    return specimenTypes; 
} 

public void setSpecimenTypes(List<SpecimenType> specimenTypes) { 
    this.specimenTypes = specimenTypes; 
    if(this.specimenTypes != null){ 
     for(SpecimenType specType : this.specimenTypes){ 
      specType.setReportCriteriaBean(this); 
     } 
    } 
} 

子オブジェクトコード:

public ReportCriteriaBean getReportCriteriaBean() { 
    return reportCriteriaBean; 
} 
public void setReportCriteriaBean(ReportCriteriaBean reportCriteriaBean) { 
    this.reportCriteriaBean = reportCriteriaBean; 
} 

親設定を休止

EDIT:

明らかに私の問題は、DBから親オブジェクトを取得した後、更新されたオブジェクトを元に戻す前に、明示的にsetSpecimenTypes()を呼び出すためです。私はこれをやっている理由は、いくつかの動的なListバインディングのために、UIに提示されるListがList(具体的にはApacheのLazyList)の特定の実装である必要があるからです。しかし、オブジェクトがDBから取り出されると、この方法では実装されません。したがって、データベースから取得した正規リストのLazyListコピーを作成し、setSpecimenTypes()を呼び出して、新しく作成されたLazyListと置き換えます。誰かがこれを行う方法を知っていますか?

答えて

0

あなたのマッピングは正しいように見えます。あなたはどうやって子供を取り除いていますか? getSpecimenTypes().remove(X)に似たものか、それとも特別な方法がありますか(そうなら、それを投稿できますか?)

また、親オブジェクトがUIレイヤーに転送されて戻るとき、同じセッション内で親オブジェクトが転送されますか?途中でsetSpecimenTypes()と呼んで子どもコレクションをリセットしていない人はいませんか?

更新(明確化に基づく):

specimenTypesをリセットすると、確かに問題です。 Hibernateは、特定の要素を削除したことをどのように知っていますか?削除はHibernate自身のPersistentList内で追跡され、親オブジェクトがロードされるときにリストをラップします。

LazyList(私はCommons Collectionsのものを意味すると思います)はデコレータなので、specimenTypesコレクションをLazyListにラップして返す親オブジェクト内に別のgetterメソッドを作成して戻すことができます反復アクセス試行中の効率のための変数)。

ここで一番下の行は、Hibernateが管理するコレクションを自分のバージョンで上書きしないでください。

+0

オブジェクトを更新する前にsetSpecimenTypes()を呼び出しています(理由は私の投稿への更新で概説しています)。現在の子セットに含まれているものを反映するように子リストを更新すべきではありません。これにより古い子DBエントリは削除されますか? – TimmyJ

+0

助けてくれてありがとう。私はまだ問題を抱えています。getterを変更して装飾されたListを返すと、親クラスがDBから取得されるときに次のエラーが発生します。 cascade = "all-delete-orphan"のコレクションは所有エンティティインスタンスによって参照されなくなりました。 私は、setSpecimenTypesが呼び出されないことを確信しています(私はそれをプライベートにするために行った)。あなたは私が行ったように、現在のものを置き換えるのではなく、別のゲッターを作成すべきであることを上記で言及します。私の方法が間違っている理由はありますか? – TimmyJ

+0

既存のゲッターからデコレートされたリストを返す問題は、もはやHibernateのPersistentListではないということです。 Hibernateはあなたがそれをラップしたこと(またはそれをアンラップする方法)を知らないので、そこにあったPersistentListが今やなくなっていることがわかります - したがって、例外です。実際には別のゲッターが必要ですが、コードが 'getSpecimenTypes()'に依存している場合は、 'getSpecimentTypesDB()'をプライベートにして、それをHibernateにマップすることができます。私は個人的にはビジネスオブジェクトではなくUI Beanを装飾することを好みますが、いずれのアプローチもその場所を持っています。 – ChssPly76

関連する問題