java - 加载数据避免在持久性上下文中找到的实体

标签 java hibernate postgresql jpa persistence

我想执行一个方法 (compareEntities),该方法需要当前在数据库中的实体和刚刚保存的对象。在我的 DAO 中是这样的,其中 em 是 EntityManager:

public void save(MyObj myObj) {
    MyObj previous = null;
    MyObj current = null;
    Integer id = myObj.getId();     
    if (id == null) {
        // new
        current = em.persist(myObj);
    } else {
        previous = em.find(MyObj.class, id);
        // update
        current = em.merge(myObj);
    }
    compareEntities (previous, current);
}

问题是,由于要保存的实体来自数据库并且我对其进行了一些更改,当我尝试从数据库中获取数据时(使用 find 方法)我获取了数据进行更改,因为实体是在持久性上下文中找到的。有什么方法可以获取数据库中的数据,而无需我对同一事务中的实体所做的更改?

谢谢。

最佳答案

没有可靠的方法可以使用当前附加了同一实体的修改实例的持久性上下文来查找未更改的实体。持久性提供程序可能已将更改刷新到数据库,在这种情况下,后续的 SELECT 将显示changed 对象,因为这是事务中的当前对象。即使持久性提供程序尚未刷新更改,规范要求find 调用返回相同的实例同一个键。不允许返回“未更改”的对象。

您将需要使用另一个连接从新事务中获取数据。如何做到这一点取决于您的编程模型。在具有容器管理事务的 JTA 编程模型(如 EJB3)中,您将使用带注释的 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 业务方法。在普通 JPA 中,您将获得一个新的 EntityManager 并通过 ID 查找对象。

我怀疑您正在尝试实现审计日志系统,在这种情况下您应该查看 Hibernate Envers , PostgreSQL audit trigger example ,或标准的 JPA 实体监听器,所有这些都提供了更好的方法来完成此任务。尝试解释您要解决的根本问题,即此问题的“方法”的“原因”。

关于java - 加载数据避免在持久性上下文中找到的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12895079/

相关文章:

java - 为什么 hbm2ddl 不喜欢我在 GregorianCalendar 上的 @Temporal 注释?

sql - 如何在Postgres中实现列值变化约束

sql - 在 order by 子句中使用 bool 表达式

sql-server - SQL Server 中 CASE 语句中的 IN 条件

java - 如何将流与干扰方法和构造函数一起使用,为什么不使用 .peek()?

Java NumberFormat四舍五入模式,为什么半上格式1.015转1.01不转1.02

java.lang.ClassCastException : [Ljava. lang.Object 或 LazyInitializationException 异常

java - 使用 Spring Boot/JPA 生成唯一字段的正确方法是什么?

java - 从 array.sort() 到compareTo()

java - 由 : org. hibernate.boot.registry.classloading.spi.ClassLoadingException 引起:无法加载类 [Employee]