0

我们在这里就 JPA EntityManager 的持久性进行了一些讨论。

假设以下代码:

MyObject obj = new MyObject();
obj.setName("Lalala");
em.persist(obj);

// This is just an example to show that I intend on 
// using the obj instance after persisting.
em.flush();
System.out.println(obj.getId());

现在我对持久化的理解是它负责持久化 obj 但不会使 obj 被管理。我的同事声称 obj 现在已成为托管对象,这也是 EntityManager 的 JavaDoc 所声称的。

我现在的问题是:这怎么可能?在java中,我想不出任何逻辑

Vehicle car = new Car();
try {
    car.fillInFuel(Fuel.TRUCK_DISEL);
    Asert.fail("filling in truck fuel into a car, should theow an exception.");
} catch(BadFuleException pfe) {
    // Handle this.
}

// Now call some sort of magic, converting my car into a truck. 
// (An unmanaged entity into a managed entity)
makeTruck(car);

// treat the car as a truck from here.
try {
    car.fillInFuel(Fuel.TRUCK_DISEL);
} catch(BadFuleException pfe) {
    Asert.fail("filling in truck fuel into a truck, should work.");
}

这可能是管理实体的方式不同。我习惯使用 EclipseLink,而我的同事正在使用 Hibernate。在 EclipseLink 中,对持久性的调用不会使我传入的实体实例持久化,它只是负责保存数据。如果我想继续处理托管实体,我必须改用合并。

if(!em.contains(obj)) {
    obj = em.merge(obj);
} else {
    em.persist(obj);
}

我知道在 EclipseLink 中,托管实体与非托管实体不同,因为更改跟踪是在实体中完成的,而在 Hibernate 中,似乎根本没有跟踪更改。

那么......谁是对的?EclipseLink 和 Hibernate 对 EntityManager 类的 Api-Docs 的解释是否完全不同?EclipseLink 之一是否正确?

克里斯

4

1 回答 1

1

文档是正确的(您的同事是正确的)。

我不太了解您的示例与 Car/Vehicle 与实体的托管状态之间的关系。但是,如果您想知道 JPA 提供程序如何正确处理,那就是另一个问题了。一个可能的解决方案如下:在持久化时,将orig实体复制到copy并在事务提交时,将copy实体与托管orig实体进行比较。当然还有更复杂的解决方案(比如 AspectJ),尽管我认为它们没有在任何 JPA 提供程序中使用。

为了测试 Eclipse/Hibernate 是否将实体置于托管状态,请尝试以下操作:

em.persist(obj);
if(!em.contains(obj)) {
    //print TRUE
} else {
   //print FALSE
}

我知道在 EclipseLink 中,托管实体与非托管实体不同,因为更改跟踪是在实体中完成的,而在 Hibernate 中,似乎根本没有跟踪更改。

在休眠(或任何 JPA 提供程序)中,托管实体的更改也被跟踪(只是它们可能在另一个时间被刷新)。通过跟踪我的意思是,它们被识别(更早或更晚),并且不一定在它们被制造时被跟踪。

另请注意,我们在这里谈论的是在同一类方法中使用容器管理的实体管理器对实体进行的更改。

于 2013-11-01T10:32:55.717 回答