防止Hibernate会话刷新/存储无效的脏实体

时间:2014-04-22 08:14:36

标签: java hibernate session validation

我想知道采取哪种方法来防止Hibernate 4.3.4(使用Spring和Hibernate Vaidator)来清除脏实体。 在我的代码中,我使用Hibernate Validator的手动实现(实例本身中的.validate()方法),在保存实体之前调用它。 validate()方法返回错误列表(如果找到),否则调用Session.update()来存储实体,然后提交事务。

这是有效的,但是当操作实例本身(在实体中设置发布/请求参数)时,实体和相应的Hibernate会话被标记为“脏”,并且实体与下一个Session.flush()一起存储。

在我的情况下,我想明确控制可能存储的实体并防止存储任何脏实体,我将如何实现这一目标?

修改

我知道我可以通过驱逐实体(或通过合并清算和重新引入实体)来手动调节这一点,但这不是我的目标。我不想手动调节持久性,而是希望有一个偏移情况,即没有明确保存的实体以及未明确提交事务的实体将不会存储到数据库中(例如通过拦截器?)。

1 个答案:

答案 0 :(得分:8)

如果修改实体并明确要求不刷新它们,则可以在修改之前将它们分离。分离的实体将不再由持久性上下文管理。

Hibernate API:

session.evict(myEntity)

JPA:

entityManager.detach(myEntity)

编辑:如果您想要分离所有实体并仅管理其中一些实体,您可以先清除持久性上下文,然后合并执行所需的实体管理:

Hibernate API:

session.clear();
managedEntity = session.merge(detachedEntity);

JPA:

entityManager.clear();
managedEntity = entityManager.merge(detachedEntity);

编辑2 管理实体的所有更改都会在事务提交时刷新。我不知道JPA或Hibernate的任何功能可以关闭此行为。因此,除了分离一些或所有实体之外,您还有其他选择,但没有一个是您正在寻找的:

  • 获取事务外的实体,因此它们会立即分离。这似乎最接近你想要的 - 没有管理变更的麻烦,只有显式合并会保存一个实体,你将不得不减少持久性API。但是,您仍然需要打开一个会话来合并您想要保存的实体和更改。

  • 使用查询中的NEW运算符将查询结果映射到DTO / POJO(始终分离)。此方法具有将持久性映射与应用程序分离的优点。然而,引入一堆新类可能不值得,并且在整个应用程序中不一致地添加它会增加概念上的复杂性。

  • 在事务中工作,但是回滚而不是提交。您将无法保存任何内容,这是防止更改与数据库同步的粗略方法。不幸的是,您必须最终提交或回滚事务。

  • 创建实体的深层副本以更改它们。坦率地说,这对我来说并没有多大意义,只是为了完整起见而添加它。

编辑3 虽然JPA规范未指定,但Hibernate和Eclipselink都允许将单个查询中的事务或结果集标记为只读。这可能对你有用,如

  

当持久对象是只读的时,Hibernate不会脏检查简单属性

当谈到关系时,改变冲洗会变得更复杂一些。请参阅this documentation for Hibernatethis one for Eclipselink