2012-08-08 43 views
0

我使用Hibernate 3.6.10來持久保存一組對象。對象B包含一個參考對象A:使用持久化版本替換淺層Hibernate對象

@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; 
} 

我試圖用一個堅持ObjectA參考創建ObjectB新實例,而不首先從數據庫中裝載的ObjectA實例。例如:然而

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) 

顯而易見的解決方案是加載的ObjectA通過ID實例,但我試圖解決的情況下的ObjectB的實例通過從JSON反序列化創建:

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

我想解決這個問題,一般情況下代碼做反序列化ca n可以與任何映射的Hibernate對象一起工作,而不必知道它的結構。鑑於這樣一個反序列化的對象,我可以用遞歸遞歸遍歷ObjectB的所有映射字段,並用它們的持久等價物(可能使用Session.merge(…))「補充水分」,但這聽起來像一個解決的問題,我不想重新創建車輪。

回答

0

我希望找到一個現有的解決方案,但它似乎不存在。所以我寫了我自己的。這沒有經過徹底測試(雖然我確實有一套集成測試),並且不支持所有類型的Hibernate映射,但它適用於我的目的。來源是here。它支持任意嵌套的對象。

1

你描述的問題沒有解決(或者我可以用任何ORM解決)。如果你想休眠來管理對象關係,你需要從數據庫加載對象或調用merge()。當你調用save()時,所有的對象樹都需要通過hibernate或需要插入的新對象來跟蹤。

避免這種情況的方法是自己管理關係,但這會降低使用hibernate的價值。您可以嘗試檢查MyBatis是否具有支持所需用途的功能,因爲您可以操縱持久對象的方式。