0

オブジェクトのセットを永続化するためにHibernate3.6.10を使用しています。オブジェクトBには、オブジェクトAへの参照が含まれています。

@Entity
@Table(name = "OBJECT_A")
class ObjectA {
    @Id
    String id;

    @Basic
    String name;
}

@Entity
@Table(name = "OBJECT_B")
class ObjectB {
    @Id
    String id;

    @ManyToOne(optional = false)
    @Cascade({CascadeType.SAVE_UPDATE})
    ObjectA objectA;

    @Basic
    String name;
}

最初にデータベースからのインスタンスをロードせずObjectBに、persistedへの参照を使用しての新しいインスタンスを作成しようとしています。例えば:ObjectAObjectA

ObjectA objA = new ObjectA();
objA.id = 42; // same ID as persisted object, but not loaded from db

ObjectB objB = new ObjectB();
objB.objectA = objA;
objB.name = "The Answer";

session.save(objB);

session.save(objB)ただし、失敗します。

org.hibernate.PropertyValueException: not-null property references a null or transient value: ObjectA.name
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:100)

明らかな解決策は、のインスタンスをidでロードすることですが、JSONから逆シリアル化することによってObjectAのインスタンスが作成される場合を解決しようとしています。ObjectB

{
    "ObjectB" : {
        "objectA" : {"id" : 42},
        "name" : "The Answer"
    }
}

デシリアライズを実行するコードが、その構造を知らなくても、マップされたHibernateオブジェクトで機能できる一般的なケースでこれを解決したいと思います。このような逆シリアル化されたオブジェクトを考えると、リフレクションを使用して、マップされたすべてのフィールドを再帰的にウォークし、ObjectBそれらを永続的な同等のもので「再水和」することができます(おそらくを使用してSession.merge(…))が、これは解決された問題のようなにおいがするので、車輪の再発明はしたくありません。

4

2 に答える 2

1

あなたが説明する問題は解決されていません(または私が知っているORMで解決可能です)。オブジェクトの関係を管理するために休止状態にする場合は、DBからオブジェクトをロードするか、merge()を呼び出す必要があります。save()を呼び出すときは、すべてのオブジェクトツリーを、休止状態または挿入する必要のある新しいオブジェクトによって追跡する必要があります。

これを回避する方法は、関係を自分で管理することですが、これにより、休止状態を使用する価値が低下します。オブジェクトがどのように永続化されるかを操作できるので、MyBatisに必要な使用をサポートする機能があるかどうかを確認することができます。

于 2012-08-08T12:42:24.400 に答える
0

私は既存の解決策を見つけたいと思っていましたが、何も存在しないようです。だから私は自分で書いた。これは完全にテストされておらず(統合テストのスイートはありますが)、すべてのタイプのHibernateマッピングをサポートしているわけではありませんが、私の目的にはうまく機能しています。ソースはこちらです。任意にネストされたオブジェクトをサポートします。

于 2012-08-11T10:00:57.737 に答える