java - 如何判断当前 session 是否脏?

标签 java hibernate spring-mvc jpa

当且仅当数据库发生更改时,我想发布一个事件。我在 @Transaction 下运行的是 Spring 上下文,我想出了这个检查:

    Session session = entityManager.unwrap(Session.class);
    session.isDirty();
对于新的( transient )对象,这似乎失败了:
@Transactional
public Entity save(Entity newEntity) {
    Entity entity = entityRepository.save(newEntity);
    Session session = entityManager.unwrap(Session.class);
    session.isDirty(); // <-- returns `false` ):
    return entity;
}
基于这里的答案 https://stackoverflow.com/a/5268617/672689我希望它能够工作并返回 true。
我错过了什么?
更新
考虑到@fladdimir 的回答,虽然这个函数是在事务上下文中调用的,但我确实添加了 @Transactional (来自 org.springframework.transaction.annotation)关于函数。但我仍然遇到相同的行为。 isDirty 返回 false。
此外,正如预期的那样,当程序停留在 session.isDirty() 行的断点处时,新实体不会显示在数据库上。 .
更新_2
我还尝试在调用 repo save 之前更改 session 刷新模式,也没有任何影响:
    session.setFlushMode(FlushModeType.COMMIT);
    session.setHibernateFlushMode(FlushMode.MANUAL);

最佳答案

首先,Session.isDirty()和我理解的意思不一样。它告诉当前 session 是否保留在尚未发送到数据库的内存查询中。虽然我认为它会告诉交易是否有变化的查询。保存新实体时,即使在事务中,插入查询也必须发送到数据库以获取新实体 id,因此在它之后 isDirty() 将始终为 false。
所以我最终创建了一个类来扩展 SessionImpl 并保存 change session 的状态,在持久和合并调用时更新它( hibernate 正在使用的功能)
所以这是我写的类:

import org.hibernate.HibernateException;
import org.hibernate.internal.SessionCreationOptions;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.SessionImpl;

public class CustomSession extends SessionImpl {

    private boolean changed;

    public CustomSession(SessionFactoryImpl factory, SessionCreationOptions options) {
        super(factory, options);
        changed = false;
    }

    @Override
    public void persist(Object object) throws HibernateException {
        super.persist(object);
        changed = true;
    }

    @Override
    public void flush() throws HibernateException {
        changed = changed || isDirty();
        super.flush();        
    }

    public boolean isChanged() {
        return changed || isDirty();
    }
}
为了使用它,我必须:
  • 延长 SessionFactoryImpl.SessionBuilderImpl覆盖 openSession函数并返回我的 CustomSession
  • 延长 SessionFactoryImpl覆盖 withOptions函数返回扩展 SessionFactoryImpl.SessionBuilderImpl
  • 延长 AbstractDelegatingSessionFactoryBuilderImplementor覆盖 build函数返回扩展 SessionFactoryImpl
  • 实现 SessionFactoryBuilderFactory实现 getSessionFactoryBuilder返回扩展 AbstractDelegatingSessionFactoryBuilderImplementor
  • 添加 org.hibernate.boot.spi.SessionFactoryBuilderFactory META-INF/services 下的文件,值为 my SessionFactoryBuilderFactory实现完整的类名(让 spring 知道它)。

  • 更新
    捕获“合并”调用时存在一个错误(如 7 条评论),因此我最终在任何刷新之前捕获了 isDirty 状态,并在检查 isChanged() 时再次检查它。

    关于java - 如何判断当前 session 是否脏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67619442/

    相关文章:

    java - 在 hibernate 中关闭 import.sql

    java - 从模型声明并初始化 JSP 中的对象

    spring-mvc - 如何将 JasperReportsMultiFormatView 与 ContentNegotiatingViewResolver 一起使用?

    java - 是否可以在不使用 if 语句的情况下找出哪个数字更大?

    java - 面试问题 - 如何处理基于 SOAP 和基于 REST 的异常

    java - 带有 IntelliJ 的 opencsv

    java - Oracle 中的 JPA 和 Flyway boolean 类型

    java - Elasticsearch 失败,错误为 "Failed to execute phase [query_fetch], all shards failed"

    java - 使用 CriteriaQuery 选择通用主键

    web-services - 2 个 REST Web 服务之间的通信