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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23100888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 20:41:13  来源:igfitidea点击:

Why is "hibernate.connection.autocommit = true" not recommended in Hibernate?

javadatabasehibernatetransactionsautocommit

提问by Ponmudi VN

In Hibernate API, there is a property hibernate.connection.autocommitwhich can be set to true.

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

But in the API, they have mentioned that it is not recommended to set it like so:

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

Enables autocommit for JDBC pooled connections (it is not recommended).

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

Why is it not recommended ? What are the ill-effects of setting this property to true ?

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

回答by Craig Ringer

My understanding is that if Hibernate autocommits, then a flush that fails part way through won't be rolled back. You'll have an incomplete/broken object graph.

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

If you want a connection with autocommit on for something, you can always unwrap a newly created Sessionto get the underlying JDBC Connection, setAutocommit(true)on it, do your work via JDBC APIs, setAutocommit(false), and close the session. I would notrecommend doing this on a Sessionthat's already done anything.

如果你想要一个带有自动提交的连接,你总是可以解开一个新创建的Session以获取底层 JDBC 连接,setAutocommit(true)在它上面,通过 JDBC API 完成你的工作setAutocommit(false),然后关闭会话。我建议在Session已经做过任何事情的人上这样做。

回答by user3145373 ツ

By default the autocommit value is false, therefore the transaction needs to be commited explicitly. This might be the reason why the changes not getting reflected in database, else can try flush to force the changes before commit.

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

When you close the session, then it will get commited in database implicitly [depends on the implementation].

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

When you have cascading transactions & needs to rollback for atomicity, you need to have control over transactions & in that case, autocommit should be false.

当您有级联事务并需要回滚原子性时,您需要控制事务,在这种情况下,自动提交应该是假的。

Either set autocommit as true or handle transactions explicitly.

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

Hereis a good explanation on it.

是一个很好的解释。

Hibernate forumrelated to this.

Hibernate 论坛与此相关。

Stackoverflow questionon it.

Stackoverflow 上的问题

回答by Vlad Mihalcea

All database statements are executed within the context of a physical transaction, even when we don't explicitly declare transaction boundaries(BEGIN/COMMIT/ROLLBACK).

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

If you don't declare the transaction boundaries, then each statement will have to be executed in a separate transaction. This may even lead to opening and closing one connection per statement.

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

Declaring a service as @Transactional will give you one connection for the whole transaction duration, and all statements will use that single isolation connection. This is way better than not using explicit transactions in the first place. On large applications you may have many concurrent requests and reducing database connection acquiring request rateis definitely improving your overall application performance.

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

So the rule of thumb is:

所以经验法则是:

  1. If you have read-only transactions that only execute one query, you can enable auto-commit for those.

  2. If you have transactions containing at more than one statement, you need to disable auto-commit, since you want all operations to execute in a single unit-of-work and you don't want to put extra pressure on your connection pool.

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

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

回答by newday

Do not use the session-per-operation antipattern: do not open and close a Session for every simple database call in a single thread. The same is true for database transactions. Database calls in an application are made using a planned sequence; they are grouped into atomic units of work. This also means that auto-commit after every single SQL statement is useless in an application as this mode is intended for ad-hoc SQL console work. Hibernate disables, or expects the application server to disable, auto-commit mode immediately. Database transactions are never optional. All communication with a database has to occur inside a transaction. Auto-commit behavior for reading data should be avoided, as many small transactions are unlikely to perform better than one clearly defined unit of work. The latter is also more maintainable and extensible.

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

find more information on this topic

查找有关此主题的更多信息