0

次の状況を考えてみましょう。休止状態によって永続化されるオブジェクトがあります。オブジェクトには、それ自体が大量の属性を持つ一連のオブジェクト属性があります。そのようです:

Mainobject
|-Subobject A
|--String xyz
|-- ...
|-Subobject B
|-- ...
|-Subobject C
|- ...

メイン オブジェクト テーブルは、ほとんどサブ オブジェクト テーブルを参照するだけです。

オブジェクトの保存と読み込みは問題ありません。たとえば、xyz などのサブオブジェクト属性の値を変更しても更新されません。ただし、すべてのサブオブジェクトの新しいインスタンスを作成し、それらの新しいサブオブジェクトを既存のメイン オブジェクトに割り当てる必要がある場合があります。メイン オブジェクトを saveOrUpdate すると、(明らかに) サブオブジェクトごとに新しい行が取得され、メイン オブジェクトが新しい参照で更新されます。

ただし、代わりに達成したいのは、Hibernate が新しいオブジェクトの新しい行を作成せず、代わりに古い行を更新することです。

どうすればこれを達成できますか?(サブオブジェクトをロードして、そのすべての新しい属性を手動で割り当てることもできますが、それらの数が多すぎて、実際には良い方法とは思えません)

ありがとうございました!

編集:非常に基本的なサンプルコード

Mainobject obj = dao.get(MainObject.class, 1L);
obj.setSubobjectA(new SubobjectA());
obj.setSubobjectB(new SubobjectB());
dao.saveOrUpdate(obj);

別の編集: 結合されたキーはありません。すべてのオブジェクト/テーブルには 1 つの PK があります。メインオブジェクト テーブルは、サブオブジェクト テーブルへの参照/外部キーを保持します。

編集 (ユーザー 226.. の場合): これは、メイン オブジェクトがどのように見えるかです。

@Entity
@Table(name="mainobjects")
public class MainObject 
{
    @Id @GeneratedValue
    private Long mainOjectId;

    @OneToOne
    @JoinColumn(name="ref_subobjectA_id")
    @Cascade({CascadeType.SAVE_UPDATE})
    private SubobjectA subobjectA;

    @OneToOne
    @JoinColumn(name="ref_subobjectB_id")
    @Cascade({CascadeType.SAVE_UPDATE})
    private SubobjectB subobjectB;

// getters / setters
}

subobjectA は次のようになります。

@Entity
@Table(name="subobjectsa")
public class SubobjectA 
{
    @Id
    private String subobjectaId;
    private String str1;
    private String str2;
    private String ....
...
// getters/setters
}

SubobjectB はほとんど同じように見えます。

コードでは、オブジェクトが存在するかどうかを調べています。

List<MainObject> existingMainObjects = dao.findByAttributes(MainObject.class, attributeNames, attributeValues);

保存しない場合は、問題ありません。存在する場合は、既存のメインオブジェクトのサブオブジェクトを別のメインオブジェクトのサブオブジェクトに置き換えます(これはデータベースに永続化されていません):

if (existingMainObjects.size() == 1)
{
existingMainObjects.get(0).setSubobjectA (someNewMainObject.getSubobjectA);
existingMainObjects.get(0).setSubobjectB (someNewMainObject.getSubobjectB);

dao.saveOrUpdate(existingMainObjects.get(0));
}

繰り返しますが、これはメインオブジェクトの新しいエントリを作成しませんが、サブオブジェクトの場合 (Hibernate によって永続化されたオブジェクトとは異なるオブジェクトであるため)、新しいエントリを作成し、メイン オブジェクトを新しい参照で更新します。基本的に達成したいのは、サブオブジェクトの値のみが置き換えられることです。

私の現在の回避策には、beanutils を使用して、キー以外のすべてのプロパティを新しいオブジェクトから既存のオブジェクトにコピーすることが含まれます。これは機能しますが、これを数万回行う必要がある場合、おそらく非常に非効率的です。

編集: 一時的な解決策 OK、 MainObject で saveOrUpdate の代わりにマージを使用するとうまくいくはずだと考えていました。しかし、そうではありません。次に、各サブオブジェクトで個別にマージ機能を使用してみることにしました。これは何らかの理由で機能するようです。メインオブジェクトをマージしただけで機能しない理由を誰か説明できますか?

4

1 に答える 1

1

2 つの新しいオブジェクトを MainObject に設定しています。外部キーで新しいオブジェクトを設定すると、MainObjecct が SubobjectA と SubobjectB を参照すると言ったので、Hibernate はメイン テーブル、つまり SubobjectA と SubobjectB でこれらのオブジェクトを検索します。一致が見つかった場合は問題ありません。それ以外の場合は、そこに新しいエントリを作成し (SubobjectA と SubobjectB を個別に)、MainOject を挿入します。

できることは、SubobjectA と SubobjectB に既に存在するオブジェクト (SubobjectA と SubobjectB) のみを MainObject に配置することです。新しいエントリの場合、最初に SubobjectA と SubobjectB に挿入し、次に MainObject に挿入します。

于 2013-07-18T19:12:09.500 に答える