【问题标题】:Hibernate internal functioning休眠内部功能
【发布时间】:2017-10-12 09:29:27
【问题描述】:

我正在开发 Spring + Hibernate 应用程序。我们已经为服务类方法应用了事务。我的问题

  1. hibernate 是否可以使用单个连接/会话或使用多个连接来执行服务方法的所有 db 语句?如果它使用多个连接,是否可以在任何运行时异常的情况下回滚多个连接上的 db 语句?

  2. 假设如果服务方法的业务逻辑执行时间超过 removeAbandonedTimeout 值,那么在放弃连接时如何提交/回滚?

如果我在哪里错了,请纠正我。提前致谢。

更新:-

如果查询花费的时间比 removeAbandonedTimeout 长,它会抛出异常。假设我的服务方法有两个数据库调用,在这两个调用之间有一些业务逻辑(没有数据库调用)。在执行第一个查询之前,它会创建数据库连接,假设第一个数据库调用需要 1 秒,然后业务逻辑执行需要 60 秒。如果此时放弃连接(如果我们将 removeAbandonedTimeout 设置为 60 秒),要执行第二个数据库查询,它会创建另一个连接,对吗?如果第二个查询执行失败,它必须回滚第一个查询,因为它们都共享相同的事务。放弃连接怎么会发生这种情况?

【问题讨论】:

  • 当事务超时或异常发生时,Hibernate 会回滚整个事务,不管连接数多少。
  • @Transactional on 方法将打开一个会话,即一个连接。提交/回滚将在方法退出时完成。默认适用于每个 runtimeException -> 回滚
  • @Zeromus 好的。但是如果连接在执行过程中被放弃怎么办?
  • 假设它会抛出一个 jdbc4.CommunicationsException 并从那里回滚事务
  • 我的问题更新了,请检查。

标签: java database hibernate jdbc


【解决方案1】:
  1. Hibernate 会按照您的指示进行操作:

与spring集成时,会使用spring管理的事务。检查您在哪里打开/关闭 tx(在公共方法上使用 @Transactional 或直接使用 TransactionTemplate):内部的所有休眠查询都将在同一个事务中运行。

  1. 这是一个与您的连接池有关的问题 (dbcp ?)。不要激活removeAbandonedTimeout 标志:removeAbandonedOnMaintenance:来自文档:

将其中一项或两项设置为 true 可以恢复数据库连接 来自无法关闭连接的编写不佳的应用程序。

如果您使用典型的 spring/hibernate 编码模式,那么您的应用程序编写并不差(从数据库资源的角度来看),因此无需激活此标志:让您的长时间运行的线程保持它的事务。如果一个操作在没有运行任何数据库查询的情况下运行得很慢(它会触发 dbcp 清理),你有两个选择:

  • 不要保持与数据库的连接:将事务一分为二:一个在长时间运行的进程之前,一个在之后
  • 如果您需要保持 tx 处于打开状态(例如,因为您有不想丢失的数据库锁定),请尝试使用 cpu 采样工具优化中间的代码。

【讨论】:

  • 感谢您的解释。我的问题已更新,请您查看我的更新。
  • 我不知道,但老实说,您不应该激活“放弃”动作收集:数据库连接池无法知道连接是否真的被放弃。即使您的第二个查询被允许使用新连接(和新事务)运行,第一个查询也将被回滚,这可能会使整个过程看起来正常,但数据不一致。
【解决方案2】:

回答您的问题:

  1. 通过单个连接,我们可以执行服务的所有 db 语句。我们不能一次通过多个连接回滚 db 语句。

  2. 通常,removeAbandonedTimeout 值应设置为您的应用程序可能具有的最长运行查询。如果 removeAbandonedTimeout 超过并且如果 removeAbandoned = true,则可以恢复数据库连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 2017-01-17
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多