场合
我有一个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
}
}
}
}
答案 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中运行。这是我选择的解决方案。