EntityManager.persist是否使实体在托管中传递,或者它是否只是创建一个托管实体,而传入的对象保持不变?

时间:2013-11-01 10:25:53

标签: hibernate jpa eclipselink

我们正在讨论有关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中,对persist的调用不会使我传入的实体实例持久管理,只需保存数据即可。如果我想继续处理托管实体,我必须使用merge。

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

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

所以......谁是对的?在EclipseLink和Hibernate中,EntityManager类的Api-Docs的解释是否完全不同? EclipseLink的其中一个是否正确?

克里斯

1 个答案:

答案 0 :(得分:1)

documentation是对的(你的同事是对的)。

我真的不了解您的示例与Car / Vehicle的关系与实体的托管状态。但是,如果您想知道JPA提供程序如何正确处理,那么这是另一个问题。可能的解决方案如下:on persist,将orig实体复制到copy并在事务提交上,将copy实体与托管orig实体进行比较。当然也有更复杂的解决方案(如AspectJ),虽然我不认为它们被用于任何JPA提供商。

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

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

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

在hibernate(或任何JPA提供程序)中,还会跟踪托管实体的更改(仅限于它们可能在其他时间刷新)。通过跟踪我的意思是,它们被识别(早期或晚期),并且不一定跟踪它们。

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