Java JPA:如何检查实体是否不同步(或“脏”)或被通知脏状态的更改

时间:2014-02-12 09:43:37

标签: java jpa persistence

场合

我有一个Web应用程序,它使用JPA作为底层数据库的链接。当用户通过UI修改实体时,这些更改不会立即保存到数据库中。

问题

如何检查实体和基础数据库是否不同步(即实体)。

此外,是否可以自动通知此情况,例如通过监听机制?

这是否可以使用JPA规范?我目前使用Hibernate作为底层持久性管理器,但JPA(EntityManager)中的解决方案会更好。

如果无法使用JPA,也欢迎使用Hibernate 4持久性API的解决方案!

目的

我想用它来将脏对象的UI表示标记为脏。

更长版本

加载Web UI后,将从数据库加载实体。然后,用户可以在UI中修改这些实体。但是,这些更改不会立即保存到数据库中。

为此,用户必须按下保存按钮,该按钮在持久性模块中执行以下代码:

// in data-persistency module
public class MyObjectManager {
    ...
    public void saveMyObject(MyObjectEntity moe) {
        ...
        EntityManager em = DatabaseJPAConnector.getEntityManager();  
        em.getTransaction().begin();
        moe.saveOrUpdate(em); // persists or merges moe and all its childs
        em.getTransaction().commit();
        ...
    }
    ...
}

为了测试一个对象是否不同步,我想要一个方法来验证一个Entity当前是否是脏的和/或一个事件机制,以便在脏状态改变时自动通知感兴趣的GUI元素:

// in data-persistency module
public class MyObjectManager {
    ...
    public boolean isDirty(MyObjectEntity moe) {
        ...
        EntityManager em = DatabaseJPAConnector.getEntityManager();  
        return ???
    }
    ...
    public void addDirtyListener(DirtyStateListener listener) {
        // publisher-subscriber pattern
    }
}

// in gui module
public class MyGUIComponent {
    if (data.isDirty(moe)) {
        // mark UI object as dirty
    }

    MyGUIComponent() {
        data.addDirtyListener(new DirtyStateListener() {
            public void dirtyStateChanged(DirtyStateEvent event) {
                // update dirtyness state of UI object
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用实体侦听器(请参阅JPA 2.1规范的第3.5章)。在@PostUpdate@PostRemove方法中,您可以触发CDI事件 - 请参阅第3.5.1节。但是这个解决方案有它的局限性......

Entity listener classes in Java EE environments support dependency injection through the 
Contexts and Dependency Injection API (CDI) [ 10 ] when the containing archive is a bean 
archive.

其他解决方案是使用乐观锁定和@Version属性。这是一个更简单的解决方案,它甚至可以在JPA 1.0中运行。这是我选择的解决方案。