Hibernate 批处理:无状态会话 VS 常规会话本机查询

Hibernate Batch process : Stateless Session VS Regular Session Native Query

据我所知,到目前为止,在使用批处理时首选无状态会话,因为它只会分离执行该过程的对象,因此持久上下文和缓存将是免费的,因此批处理是闲置的情况,众所周知作为普通的 JDBC 查询引擎,查询立即转换为 SQL 查询。 引用自:

另一方面,我了解到本机查询做同样的事情,我看到的一个区别是无状态会话可以将结果映射到实体,本机查询在明确提供映射器之前不会这样做。

那么还有其他区别吗?从性能的角度来看,在进行批处理时哪个更好?

一如既往,如果谈到性能,最好的办法就是衡量。没有人能说出哪个在您的设置中会更好,我们不知道您使用的是哪个数据库、哪个 Hibernate 版本、哪个 OS 等。取决于很多因素。

但是,如果涉及到性能,您能做的最好的事情就是使用本机查询。如果您可以简单地将您的更新逻辑放入查询中,那就去做并执行查询。在这种情况下,数据库将处理性能最佳的所有内容。

如果您需要使用实体,请使用无状态会话,因为正如您提到的那样,它使您可以将查询结果映射到实体。虽然,无状态查询和本机查询之间还有其他区别:

使用无状态会话你将失去:

  • 一级缓存
  • 二级缓存
  • 任何拦截器机制,因为它绕过了一切
  • 自动脏检查
  • 级联

当然失去这些也意味着性能,但如果其中任何一个对你很重要,那么最好避免。

如果您想使用常规会话,也可以使用 JDBC 批处理,这可以大大提高性能,但请确保定期刷新和清除持久性上下文以避免增加缓存.

如果批处理是指通过 SQL 查询本身(例如 UPDATE things SET daily_quota=15)修改数据库服务器中的实体,那么本机 SQL 更快。但是,在这种情况下,您没有加载任何实体,因此这似乎与您的问题不符。

如果批处理是指修改程序中的实体(例如加载所有 Thing 实例,将 dailyQuota 属性修改为 15 并编写更新,那么您将需要无状态会话。

使用本机查询检索对象不会为您提供任何修改对象的机制。您仍然需要将它合并回持久性上下文并刷新这些更改。一旦你这样做了(假设你没有无状态会话)那么它将使用经典的 change-detecting & cache-keeping 刷新机制。

另一方面,无状态会话为您提供了一种修改程序中的实体的方法,而无需强制 ORM 层通过缓慢的更改检测过程。

你好,在进入 Hibernate 无状态会话之前,我会认真地问自己为什么需要它。首先,您已经了解了使用无状态会话时将失去的想法和功能。

即使休眠会话消耗内存,在大多数情况下您仍然可以获得不错的性能速度。如果你不能这样做,你的代码中可能还有其他问题。

我想强调的是,无状态会话不会级联持久化、合并等操作。这将删除您通常通过休眠收到的授权的重要元素。这可能会长期影响您的代码 运行 的可维护性和更改的便利性。

由于在开发方面没有代码是完全静态的,因此有时会出现新功能,有些东西需要更改等等......通常乍一看简单的批次可能会变成相当大的东西。在这种情况下,您手头的功能数量真的很重要。

我认为,如果您真的迫切需要性能,那么您应该在存储库或其他方面将持久性与业务层明确分开。如果需要,您只需编写一些纯 SQL 的存储库或尽可能接近原生 sql 的东西,例如 JOOQL。

在我的职业生涯中,我看到一些使用正常休眠会话编写的相当复杂的批处理 运行考虑到 SLA 时,它们非常好。我有一个批处理的例子 运行ning 超过 2000 分布式 事务每秒超过 16 个 cpus writen 使用 Hibernate 和正常会话。

在极少数需要大量性能的情况下,我只会使用 JOQL,因为它是最接近 SQL 的东西,它维护 ORM 关系。