提交或者设置conn.setAutoCommit(true)

12

我注意到一些程序员使用COMMIT,其他人使用conn.setAutoCommit(true);来结束事务或回滚,那么使用其中一个的好处是什么,与另一个有何不同?

它们之间的主要区别在哪里?

conn.setAutoCommit(true);

超过

statement.executeQuery(query);
statement.commit();

1
它们是针对不同目的的独立工具。其中一个并不比另一个“更好”或“更正确”。 - Affe
当在网络上使用提交客户端时,即使刷新结果集,也无法看到新记录,但是当将其设置为自动提交为true时,它可以正常工作,这就是我的问题。 - Motasem
这些问题显示了对这两种方法的误解。正如Affe所说,它们根本不是同一回事。当启用自动提交模式时,每个语句都会自动提交。当启用时,事务会隐式启动,并且必须调用commit()来实际提交它们(即使没有显式启动事务)。commit()提交一个打开的事务。setAutoCommit确定是否隐式或显式地启动事务(有点类似)。 - Corbin
据我所知,提交后将驱动程序更改为“autoCommit = true”不符合JDBC规范(尽管您需要读懂其含义)。 - Mark Rotteveel
2个回答

14
一般情况下,您应该使用Connection.commit()而不是Connection.setAutoCommit(true)来提交事务,除非您要从使用事务切换到“每个语句的事务”模型的自动提交。
尽管如此,在事务中调用Connection.setAutoCommit(true)将提交事务(如果驱动程序符合JDBC 4.1规范的第10.1.1节)。但是,您只有在打算在那之后保持自动提交时才应该这样做,因为启用/禁用连接上的自动提交可能会比简单地提交更耗费连接资源(例如,因为它需要在事务管理器之间进行切换、进行额外的检查等)。
您还应使用Connection.commit()而不是使用本机SQL命令COMMIT。正如Connection文档中所述:
注意:配置连接时,JDBC应用程序应使用适当的Connection方法,如setAutoCommit或setTransactionIsolation。当存在JDBC方法时,应用程序不应直接调用SQL命令以更改连接的配置。
问题在于像commit()setAutoCommit(boolean)这样的命令可能会在后台执行更多的工作,例如关闭ResultSets和关闭或重置Statements。使用SQL命令COMMIT将绕过此操作,并潜在地使您的驱动程序/连接进入不正确的状态。

2
这不是用户所询问的内容。 - Corbin
@Corbin 我更新了我的答案。我在文本中过于关注 COMMIT - Mark Rotteveel
所以本质上 conn.setAutoCommit(true)conn.commit(); conn.setAutoCommit(true); 是相同的,对吗? - rogerdpack
1
@rogerdpack 是的,请查看setAutoCommit(boolean)的javadoc:_"如果在事务期间调用此方法并更改了自动提交模式,则会提交事务。"_ - Mark Rotteveel

5

conn.setAutoCommit(); 方法用于控制连接,您可以在一个事务中执行 X 个查询,或者每个 execute 使用一个单独的事务。

正如 API 描述的那样:

 void setAutoCommit(boolean autoCommit)
                    throws SQLException

将此连接的自动提交模式设置为给定状态。如果一个连接处于自动提交模式,则所有其SQL语句将作为单独的事务执行并提交。否则,其SQL语句将被分组为由commit方法或rollback方法调用终止的事务。默认情况下,新连接处于自动提交模式。
对于简单的情况:
conn.setAutoCommit(false); 
statement.executeQuery(query); 
statement.commit();

将会与以下内容相同:

conn.setAutoCommit(true); 
statement.executeQuery(query);

您还应该展示在单个方法中使用两个插入/更新/删除语句时的区别。 - Luiggi Mendoza
如果conn.setAutoCommit(true);,那么我将不会被保存,因为ACID是这里的优先事项,但我可以使用conn.setAutoCommit(false);语句。statement.executeQuery(query); statement.commit(); conn.setAutoCommit(true);在这种情况下会有什么反应? - Motasem
@Motasem 但是 conn.setAutoCommit(true); statement.executeQuery(query); 将会和 conn.setAutoCommit(false); statement.executeQuery(query); statement.commit(); 做相同的事情。请检查你的 statement.commit() 是否被成功调用,且没有返回任何 SQLException - MrJames
没有发现错误,但是:conn.setAutoCommit(false); 然后在事务完成后我执行了 commit(); 我检查了 autoCommit 模式的状态,发现它仍然是 false!!! - Motasem
当我开始一个事务时,我设置了conn.setAutoCommit(false);然后在事务完成后,我执行了commit()。在commit()之后,我检查了autoCommit模式的状态,发现autoCommit模式仍然是false!!!这是怎么回事? - Motasem
1
@Motasem 请阅读连接API文档。文档中指出,如果要显式使用commit(),则应禁用自动提交模式,但并未说明您的autoCommit模式会发生变化... - MrJames

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接