为啥在 Hibernate 中不推荐“hibernate.connection.autocommit = true”?

Posted

技术标签:

【中文标题】为啥在 Hibernate 中不推荐“hibernate.connection.autocommit = true”?【英文标题】:Why is "hibernate.connection.autocommit = true" not recommended in Hibernate?为什么在 Hibernate 中不推荐“hibernate.connection.autocommit = true”? 【发布时间】:2014-05-30 19:42:17 【问题描述】:

在 Hibernate API 中,有一个属性 hibernate.connection.autocommit 可以设置为 true。

但在API中,他们提到不建议这样设置:

为 JDBC 池连接启用自动提交(它不是 推荐)。

为什么不推荐? 将此属性设置为 true 有什么不良影响?

【问题讨论】:

【参考方案1】:

所有数据库语句都在物理事务的上下文中执行,即使我们没有明确声明事务边界 (BEGIN/COMMIT/ROLLBACK)。

如果您不声明事务边界,则每个语句都必须在单独的事务中执行。这甚至可能导致每个语句打开和关闭一个连接。

将服务声明为@Transactional 将在整个事务期间为您提供一个连接,并且所有语句都将使用该单个隔离连接。这比首先不使用显式事务要好得多。在大型应用程序中,您可能有许多并发请求,降低数据库连接获取请求率肯定会提高您的整体应用程序性能。

所以经验法则是:

    如果您有只执行一个查询的只读事务,您可以为这些事务启用自动提交。

    如果您的事务包含多个语句,则需要禁用自动提交,因为您希望所有操作都在单个工作单元中执行,并且您不想对连接池施加额外压力.

【讨论】:

【参考方案2】:

不要使用 session-per-operation 反模式:不要在单个线程中为每个简单的数据库调用打开和关闭 Session。数据库事务也是如此。应用程序中的数据库调用是使用计划的顺序进行的;它们被分组为原子工作单元。这也意味着在应用程序中每个 SQL 语句之后的自动提交是无用的,因为这种模式旨在用于临时 SQL 控制台工作。 Hibernate 禁用或期望应用程序服务器立即禁用自动提交模式。数据库事务永远不是可选的。与数据库的所有通信都必须发生在事务中。应该避免读取数据的自动提交行为,因为许多小事务不太可能比一个明确定义的工作单元执行得更好。后者也更易于维护和扩展。

find more information on this topic

【讨论】:

【参考方案3】:

默认情况下,自动提交值为 false,因此需要显式提交事务。这可能是更改未反映在数据库中的原因,否则可以尝试刷新以在提交前强制更改。

当您关闭会话时,它将被隐式提交到数据库中[取决于实现]。

当您有级联事务并且需要回滚以实现原子性时,您需要控制事务并且在这种情况下,自动提交应该为 false。

将自动提交设置为 true 或显式处理事务。

Here 是一个很好的解释。

Hibernate forum 与此相关。

*** question就可以了。

【讨论】:

【参考方案4】:

我的理解是,如果 Hibernate 自动提交,那么中途失败的刷新将不会被回滚。您将有一个不完整/损坏的对象图。

如果你想要一个带有自动提交功能的连接,你总是可以打开一个新创建的 Session 以获取底层的 JDBC 连接,setAutocommit(true),通过 JDBC API 完成你的工作,setAutocommit(false),然后关闭会议。我建议在已经完成任何操作的Session 上执行此操作。

【讨论】:

hibernate 在后台使用 JDBC。 autoCommit 是 JDBCConnection 的一个概念,意思是“Transaction per statement”。 transactionn = 1 sql 语句的范围 [autocommit=true] hibernate.connection.autoCommit=true 使每个语句在完成后提交,因此我们不能将 2 个或更多语句作为单个工作单元的一部分提交/回滚。我们希望 - 所有语句都运行或不运行 - 为此我们需要标记事务的开始和结束,并且我们需要禁用 autoCommit。 hibernate.connection.autocommit = false 2 场景显式事务边界:sessionFactory.openSession() session.beginTransaction() session.getTransaction().commit()//刷新会话,提交Txn session.close () 隐式事务边界 sessionFactory.openSession() //看不到事务使用情况,//但它的隐式 txn 因为 - 自动提交是假 session.flush() session.close() 这里 - 当我们关闭会话时,规范不清楚所以Oracle 中的供应商特定行为 - 所有 sql 语句都在 postgresql 中提交 - 所有 sql 语句都回滚

以上是关于为啥在 Hibernate 中不推荐“hibernate.connection.autocommit = true”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在更新事务期间休眠调用删除?

为啥需要配置数据源的 SQL 方言?

为啥 PoolingClientConnectionManager 中不推荐使用所有方法?

为啥在 DOM 级别 3 中不推荐使用 DOMSubtreeModified 事件?

为啥在 DOM 级别 3 中不推荐使用 DOMSubtreeModified 事件?

为啥在 .NET 响应式扩展中不推荐主题?