我很想知道为什么JDBC API提供自动提交模式(java.sql.Connection.setAutocommit()
)。这似乎是一种吸引人的麻烦,只会引诱人们陷入困境。我的理论是它只是添加到JDBC中,以简化那些希望创建使用JDBC编辑和运行SQL的工具的供应商的生活。有没有其他理由打开自动提交,或者它总是一个错误?
答案 0 :(得分:18)
我能看到的唯一合理的理由是在小型应用程序中简单的单一查询事务中删除connection.commit()
和connection.rollback()
样板。原始形式的JDBC本身已经需要很多样板。每一行都会让JDBC对初学者不那么可怕。
答案 1 :(得分:13)
不幸的是,使用自动提交是特定于数据库的(就像事务行为一样)。我认为如果你没有全局的,程序化的交易策略,自动提交可能比希望每个人都正确关闭/回滚交易更好。
对于MySQL,你可以默认启用autocommit = true,当你开始交易时它会自动关闭它。设置autocommit = false的唯一原因是,如果有人试图在没有BEGIN的情况下尝试启动事务,则强制发生错误。
为了简化当今典型的Java + MySQL应用程序,我或多或少会忽略自动提交设置,使用open-session-in-view模式并将其称为好。
我强烈反对显式的RDBMS行锁,而是使用乐观锁。 Hibernate提供对乐观锁的内置支持,但即使对于手动代码也是一种简单的模式,并提供更好的性能。
答案 2 :(得分:8)
我几乎总是使用autocommit = true运行。 99%的时间,我的更新是原子的。当然,有些情况下,如果您编写借记,然后尝试编写您想要回滚的信用失败。但根据我的经验,这些是相对罕见的。通常我写的每条记录都是独立的。在这种情况下,在每次写入之后不需要费心去做提交是方便的。它在这里和那里保存了一行代码。如果给定程序的结构,它意味着我不需要额外的try / catch块或者我不需要在函数之间传递连接对象,它可以节省更多。它节省了有人忘记提交的烦人的错误。
我认为它可以“引诱某人遇到麻烦”的唯一方法是他决定关闭自动提交并执行提交或回滚是太麻烦,所以他做的更新应该在一个事务中单独进行。只要没有任何事情应该中止交易,那么所有事情都可以正常工作。如果测试场景不合适,我可以想象这会进入生产阶段。
但你可以对语言的几乎任何特征说同样的话。比如,假设你编写了一个程序来处理数字,这个程序90%的时间都适合很长时间,但偶尔可能会更大。面对这种情况,正确的做法是使用BigInteger或创建一个新类来处理更大的数字。一个懒惰的程序员可能会被诱骗使用很长时间,因为它通常会起作用,而其他替代方案则太麻烦了。因此,您是否会认为Java不应该包含long(或int),因为有人可能会在不适合时使用它们?
如果在您的程序中,大多数更新必须在事务上下文中完成,则关闭自动提交。它的存在并没有伤害到你。这是方便的时候,但是当它不是你可以把它关掉。
答案 3 :(得分:7)
自动提交很方便;但是随着JDBC 3规范的改变,它变得不那么有用了。
由于“自动提交”模式下的JDBC 3连接不能打开多个Statement。执行另一个语句将关闭第一个 - 包括任何ResultSet。
因此,在SELECT中循环并发出UPDATE(甚至嵌套的SELECT)将倾向于失败。显然,实际上想要用外部SELECT的结果做某事是犯罪行为!
无论如何,取决于具体的驱动程序&版本..但一般来说,JDBC 3规范似乎要求这种无益的行为。升级驱动程序也可能无助于“发现”这种行为。
为什么要使用自动提交?最初,它是有用的&方便。正如其他答案所说,JDBC需要大量的GUFF和HANDLING来正确调用.. JDBC并不是一个设计良好的API :(
现在,您最好使用Hibernate或Spring的JdbcTemplate ..如果您正在进行servlet / Web应用程序,请进行事务管理(开始/结束)或Hibernate会话(将其绑定到本地线程)在“用户请求”的边界。
例如,在ServletRequest开始时绑定你的连接/事务;并在最后归还。
您可以使用javax.servlet.Filter或类似的东西,并将其绑定到线程本地,创建一个静态帮助器来获取它或 require 它等等。
答案 4 :(得分:5)
提交模式会更改数据库保持锁定的方式。
建议仅在事务模式下禁用自动提交模式。这样,您就可以避免为多个语句保留数据库锁,这会增加与其他用户冲突的可能性。
...
为避免事务期间发生冲突,DBMS使用锁定机制来阻止其他人访问事务正在访问的数据。 (请注意,在自动提交模式下,每个语句都是一个事务,只保留一个语句的锁。)
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
答案 5 :(得分:4)
我正在使用的95%的代码库现在涉及单个更新,其中自动提交是完全合理的。所以,我们默认它。只需将其关闭足够长的时间来完成需要成为事务的代码部分,然后自动提交将重新开启!
答案 6 :(得分:2)
在全球范围内启用“自动提交”时,某些条件需要仔细查看:
a。)查询级别的事务管理将留给用户,对于一个实例,如果需要一堆查询成功或一起失败,那么它需要被包装在BEGIN下并提交事务。
b。)请记住,启用“自动提交”时没有回滚。
c。)每次交易都有写(提交)的开销。
d。)对于只读查询,没有明确需要“自动提交”,但通过启用“自动提交”,它会自动对所有查询强制执行。
如果表锁定是启用自动提交的唯一问题,那么它可能不是一个好主意,而是可以采用较低的锁定超时。