0

我正在使用 Hibernate 3.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使用对持久对象的引用来创建新的实例,ObjectA而无需先从数据库中加载实例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"
    }
}

我想为执行反序列化的代码可以与任何映射的 Hibernate 对象一起工作而无需知道其结构的一般情况解决这个问题。给定这样一个反序列化的对象,我可以使用反射递归地遍历所有映射字段,ObjectB并用它们持久的等价物(可能使用)“重新水化”它们Session.merge(…),但这听起来像是一个已解决的问题,我不想重新发明轮子.

4

2 回答 2

1

您描述的问题没有解决(或者我知道的任何 ORM 都可以解决)。如果要休眠来管理对象关系,则需要从数据库加载对象或调用 merge()。当您调用 save() 时,所有对象树都需要被休眠或需要插入的新对象跟踪。

避免这种情况的方法是自己管理关系,但这会降低使用休眠的价值。您可以尝试检查 MyBatis 是否具有支持您想要使用的功能,因为您可以操纵对象如何持久化。

于 2012-08-08T12:42:24.400 回答
0

我希望找到一个现有的解决方案,但似乎不存在。所以我自己写了。这没有经过彻底的测试(尽管我确实有一套集成测试)并且不支持所有类型的 Hibernate 映射,但它对我的目的很有效。来源在这里。它支持任意嵌套的对象。

于 2012-08-11T10:00:57.737 回答