如何在PreUpdate中比较JPA中的两个实体

时间:2013-08-01 12:43:44

标签: java jpa persistence

我正在使用OpenJPA 2.2.1,并希望执行以下操作:

1)加载实体 2)更改实体 3)检查保存实体之前完成的更改

我做了什么:

1)通过

加载实体
    EntityManager.find(MyObject.class, id);

2)好的,很清楚,我认为,像

    MyObject obj = EntityManager.find(MyObject.class, id);
    obj.setName("New name");

3)试图从PersistenceContext中逐出对象并通过以下方式从数据库中再次加载:

    EntityManager.evict(MyObject.class, id);
    EntityManager.find(MyObject.class, id);

3)中的find()调用返回的实体总是与1)中找到的实体相等(等于ID)

我以为我可以通过evict从PersistenceContext / cache中删除实体。

如何实现两个不同的实体: a)变更的实体和 b)步骤3)中加载的数据库中的原始实体

并且:如果我刷新()实体,我希望find方法返回刷新的实体。这是对的吗?

我也尝试了@PreUpdate监听器,结果相同,所以我认为必须有一些我对JPA PersistenceContext或Java引用不了解的东西......

我希望我提供了足够的信息!提前谢谢!

3 个答案:

答案 0 :(得分:3)

为了更好地了解JPA生命周期,我发现这个站点(特别是状态图)很有帮助:http://www.objectdb.com/java/jpa/persistence/managed

主要的一点是,当您从持久化上下文中删除它们时,对象不会“消失”。您的obj仍会指向已完全初始化的MyObject,其中name设置为“新名称”。唯一的区别是提交事务/刷新持久化上下文将不再更新相应的数据库条目。

如果要在提交数据库之前查看对obj的更改,可以使用多个选项。如果快速和肮脏就够了,我建议

MyObject original = obj.clone();

并将objoriginal与您喜欢的任何工具(或只是简单地打印到日志中)进行比较。

关于refresh(),请查看this page所说的内容:

  

内存中托管对象的内容将被丢弃(包括更改,如果有),并替换为从数据库中检索的数据。这可能有助于确保应用程序处理实体对象的最新版本,以防它被检索后可能已被另一个EntityManager更改。

答案 1 :(得分:2)

如果你像我一样使用Spring @Transactional。您可以执行以下操作:

@Transactional
MyEntityObject update(MyEntityObject myEntityObject){
   boolean isNameChanged;
   em.detach(myEntityObject);
   MyEntityObject inDBObject = em.load(myEntityObject.getId());
   isNameChanged = (myEntityObject.getName() != inDBObject.getName());
} 

答案 2 :(得分:0)

怎么样:

1 /读取(或找到)对象到内存[这就是你所做的]

2 /从商店中取出物品;类似的东西:

em.getTransaction().begin();
em.remove(obj);
em.getTransaction().commit();

3 /对内存中的对象进行任何更新;

obj.setName("My New Name");

4 /最后坚持更新的对象:

em.getTransaction().begin();
em.persist(obj);
em.getTransaction().commit();

以上代码段基于javax.persistence.*;包,em是一个如此定义的实例:

EntityManagerFactory emFactory = Persistence.createEntityManagerFactory(PERSISTENT_UNIT);
EntityManager em = emFactory.createEntityManager();

一切顺利!