有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我想知道应该采取什么方法来防止Hibernate 4.3.4(使用Spring和Hibernate Vaidator)刷新脏的实体。 在我的代码中,我使用了Hibernate Validator(实例本身中的一个.validate()方法)的手动实现,它在保存实体之前被调用。validate()方法返回错误列表(如果发现),否则返回会话。调用update()存储实体,然后提交事务

这是可行的,但当实例本身被操纵(在实体中设置了POST/request参数)时,实体和相应的Hibernate会话被标记为“脏”,实体与下一个会话一起存储。刷新()

在我的情况下,我希望对可能存储的实体有明确的控制,并防止任何脏实体被存储,我将如何实现这一点

编辑:

我知道我可以通过逐出一个实体(或通过合并清除并重新引入一个实体)来手动调节这一点,但这不是我的目标。我不需要手动调节持久性,而是希望有一种补偿情况,即没有显式保存且没有显式提交事务的实体不会存储到数据库中(例如,通过拦截器?)


共 (1) 个答案

  1. # 1 楼答案

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

    Hibernate API:

    ^{}

    JPA:

    ^{}

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

    Hibernate API:

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

    JPA:

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

    编辑2事务提交时刷新对托管实体的所有更改。我不知道JPA或Hibernate的任何功能可以关闭这种行为。因此,除了分离部分或所有实体,您还有一些其他选择,但没有一个正是您想要的:

    • 获取事务外部的实体,以便立即分离它们。这似乎与您想要的最接近——管理的更改没有麻烦,只有显式合并才能保存实体,并且您需要更少地处理持久性API。但是,您仍然需要打开一个会话来合并您确实希望保存更改的实体

    • 在查询中使用NEW操作符将查询结果映射到DTO/POJO(总是分离的)。这种方法的优点是将持久性映射与应用程序分离。然而,引入一系列新类可能不值得,而且在整个应用程序中不一致地这样做会增加概念上的复杂性

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

    • 创建实体的深度副本以进行更改。坦白地说,这对我来说也没有多大意义,只是为了完整起见才添加它

    EDIT 3虽然JPA规范没有指定,但Hibernate和Eclipselink都允许将单个查询中的事务甚至结果集标记为只读。这可能对你有用,就像

    When a persistent object is read-only, Hibernate does not dirty-check simple properties

    当涉及到人际关系时,变化会变得更加复杂。请参阅this documentation for Hibernatethis one for Eclipselink