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



我目前正在实现一种方法来删除保存在多个表中的大型实体层次结构。我的目标是实现一个测试套件,它做以下事情:

  1. 像应用程序那样使用方法在DB中加载一个大的实体树
  2. 刷新实体并记住插入计数。
  3. 清除EntityManager
  4. 只加载实体根目录
  5. 删除具有应用逻辑的实体
  6. 断言删除计数等于插入计数。

测试不必是线程安全的(测试用例按顺序执行)。限制:在这个集成测试中使用内存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中的每次插入和删除,并获得受其影响的行数?是否有一个干净和健壮的方法来确保一个深度对象树的完全删除?

您可能不需要创建自己的语句拦截器,可以直接使用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导出器)。

查看Oracle教程了解JMX。

相关内容

  • 没有找到相关文章

最新更新