java 如何使用Hibernate获取插入和删除计数

7rtdyuoh  于 2022-12-25  发布在  Java
关注(0)|答案(1)|浏览(129)

我目前正在实现一种方法来删除持久化在多个表中的实体的大型层次结构。我的目标是实现一个测试套件,它可以完成以下任务:
1.像应用程序一样使用方法在DB中加载大型实体树
1.刷新实体并记住插入计数。
1.清除实体管理器。
1.仅加载实体的根。
1.删除带有应用逻辑的实体。
1.Assert删除计数等于插入计数。
测试不必是线程安全的(测试用例按顺序执行)。在此集成测试中使用内存DB是不可行的。
我正在寻找一种机制,使我能够获得自事务开始以来插入的行和删除的行的数量(无论是编程的、JPQL、Criteria API等)。为了实现这一点,我使用了以下解决方案。

class MyInsertDeleteVerifier {
    private final EntityManager em;
    private final int insertsAtStart;
    private final int deleteAtStart;
    private int insertCount;

    public MyInsertDeleteVerifier(EntityManager em) {
        this.em = em;
        this.insertsAtStart = MyStatementInterceptor.insertCount;
        this.deleteAtStart = MyStatementInterceptor.deleteCount;
    }
    /** Called after insert phase*/
    public void afterLastInsert() {
        em.flush();
        this.insertCount = MyStatementInterceptor.insertCount;
    }
    /** Called after delete phase*/
    public void afterLastDelete() {
        em.flush();
        int insertDiff = this.insertCount - this.insertsAtStart;
        int deleteDiff = MyStatementInterceptor.deleteCount - deleteAtStart;
        assert deleteDiff == insertDiff;
    }
}

该类的一个对象在事务一开始就被示例化,并根据注解进行调用,负责提供计数的类如下:

class MyStatementInterceptor implements StatementInspector {
    public static int insertCount;
    public static int deleteCount;
    
    @Override
    public String inspect(String sql) {
        if (sql.contains("insert")) {
            insertCount++;
        } else if (sql.contains("delete")){
            deleteCount++;
        }
        return sql;
    }
}

它注册为以下Hibernate属性:

<property
    name="hibernate.session_factory.statement_inspector"
    value="some.package.MyInsertDeleteVerifier"/>

这个实现的问题是它没有考虑批处理操作、@ElementCollection和JPQL。是否有一种方法可以拦截Hibernate中的每个插入和删除操作,并获得受其影响的行数?是否有一种干净而健壮的方法可以确保完全删除深层对象树?

pqwbnv8z

pqwbnv8z1#

也许您不必创建自己的语句拦截器,可以直接使用Hibernate内置的统计信息。
根据https://vladmihalcea.com/hibernate-statistics/,您只需要激活内置机制即可获得如下指标

long getEntityInsertCount()
long getEntityUpdateCount()
long getEntityDeleteCount()

甚至每个实体。您需要配置的只是属性

<property name="hibernate.generate_statistics" value="true"/>

如果希望在某个地方显示或记录这些值,JMX将是一种合适的机制:https://vladmihalcea.com/hibernate-statistics-jmx/为此,您只需再配置两个属性:

<property name="hibernate.jmx.enabled" value="true"/>
<property name="hibernate.jmx.usePlatformServer" value="true"/>

您可以使用JMX访问同一应用程序中的值,或者使用JMX监视工具(例如JVisualVm)或JMX导出器将这些值导入其他系统(例如Prometheus JMX Exporter)。
检查Oracle tutorials for an introduction into JMX

相关问题