Connection.setTransactionIsolation(int)
方法提醒:
注意:如果在事务中调用此方法,则结果是由实现定义的。
这引出了一个问题:在JDBC中如何开始一个事务? 结束一个事务很清楚,但是开启一个事务却不太明确。
如果一个Connection
在一个事务内启动,那么我们应该如何在事务外调用Connection.setTransactionIsolation(int)
以避免特定于实现的行为呢?
Connection.setTransactionIsolation(int)
方法提醒:
注意:如果在事务中调用此方法,则结果是由实现定义的。
这引出了一个问题:在JDBC中如何开始一个事务? 结束一个事务很清楚,但是开启一个事务却不太明确。
如果一个Connection
在一个事务内启动,那么我们应该如何在事务外调用Connection.setTransactionIsolation(int)
以避免特定于实现的行为呢?
回答自己的问题:
Connection.setTransactionIsolation()
可以在启用自动提交时随时调用。Connection.setTransactionIsolation()
。在事务中间调用它会导致未定义的行为。请参考Oracle的JDBC教程。
JDBC会将您在连接上执行的每个查询/更新隐式地使用事务标记。您可以通过调用setAutoCommit(false)来关闭自动提交模式并调用commit()/rollback()来指示事务的结束,以自定义此行为。伪代码:
try
{
con.setAutoCommit(false);
//1 or more queries or updates
con.commit();
}
catch(Exception e)
{
con.rollback();
}
finally
{
con.close();
}
现在,你展示的方法中有一个错误。正确的方法应该是 setTransactionIsolation(int level) 而不是用于事务标记的API。它管理着一个操作所做的更改何时/如何能够被其他并发操作所看到,这个操作是ACID(http://en.wikipedia.org/wiki/Isolation_(database_systems))中的"I"。
我建议你阅读这篇文章,就会明白:
因此,setAutoCommit(false)的第一次调用以及每次commit()的调用都隐式地标识了事务的开始。通过调用rollback()可以在提交之前撤销事务。
编辑:
请查看JDBC事务的官方文档。
创建连接时,默认情况下处于自动提交模式。这意味着每个单独的SQL语句都被视为一个事务,并且在执行后自动提交。(更精确地说,当SQL语句完成时(而不是执行时)将其提交。语句完成时,表示已检索到所有结果集和更新计数。但几乎所有情况下,语句会在执行后立即完成并提交。)
允许将两个或多个语句分组成一个事务的方法是禁用自动提交模式。以下代码演示了如何禁用自动提交模式,其中con是一个活动连接:
con.setAutoCommit(false);
令人惊讶的是,如果您希望将连接保持在“setAutoCommit(true)”模式但仍然想运行事务,则可以手动运行事务:
try (Statement statement = conn.createStatement()) {
statement.execute("BEGIN");
try {
// use statement ...
statement.execute("COMMIT");
}
catch (SQLException failure) {
statement.execute("ROLLBACK");
}
}
您可以使用以下方法进行事务处理:
con
con.setAutoCommit(false);
con.commit();
con.rollback();
con.commit();
会将要执行的 SQL 包装/添加到 BEGIN TRANSACTION;
和 COMMIT;
语句中(或者以等效的方式运行),从而省去了代码显式包含这些语句的需要。这样理解正确吗? - Agi HammerthiefsetAutoCommit(false)
在发送下一个Statement
之前为驱动程序开启了一个新的事务。 - David Bullock实际上,JDBC教程中的这个页面可能更适合阅读。
你需要获取连接,设置隔离级别,执行更新等操作,然后提交或回滚。
使用单个连接进行多个事务的操作(重用、汇集或链接),可能会出现一些奇怪的问题,这些问题可能会使人们不得不忍受,因为他们通常不能确定原因。
以下几种情况需要注意:
第1点非常简单易懂。 第2点基本上会导致第1点和/或第3点。
第3点与一个新事务在发出第一个语句之前已经开始的系统有关。从数据库的角度来看,这样的事务可能已经在“第一个”真正语句发出之前就已经开始了。如果并发模型基于快照思想,其中一个只读取在事务开始时有效的状态/值,但没有后来发生的任何变化,则在提交时非常重要验证当前事务的完整读取集合。
由于NoSQL和某些隔离级别(如MS SQL-Server快照)通常不会正确验证读取集,因此通常无法确定预期结果。虽然这是一个始终存在的问题,但当处理从上次提交或连接被池化而不是实际使用的事务时,情况会更糟。因此通常需要确保事务在预期开始时实际开始。(如果使用仅回滚只读事务,则非常重要)。
我在处理JAVA中的JDBC时使用以下规则:
只有在响应时间很关键或者没有Hibernate可用时,才会使用3+4。 4允许使用一些更高级的性能(响应时间)改进模式,适用于特定情况。