How to start a transaction in JDBC?

Connection.setTransactionIsolation(int) warns:

Note: If this method is called during a transaction, the result is implementation-defined.

This bring up the question: how do you begin a transaction in JDBC? It's clear how to end a transaction, but not how to begin it.

If a Connection starts inside in a transaction, how are we supposed to invoke Connection.setTransactionIsolation(int) outside of a transaction to avoid implementation-specific behavior?

106267 次浏览

我建议你读一下 这个,你会看到的

因此,第一个调用 SetAutoCommit (false)和每个调用 Commit ()隐式标记 交易。交易可以是 未完成之前,他们承诺 打来的

编辑:

检查关于 JDBC 事务的官方文档

当连接被创建时,它处于自动提交模式。这意味着 每个独立的 SQL 语句都被视为事务,并且是 执行后立即自动提交 则默认情况下提交 SQL 语句 完成,而不是在执行时完成 其结果集和更新计数已被检索 但是,所有的情况下,一个陈述是完成的,因此提交, 在执行后立即执行。)

允许将两个或多个语句分组到 事务是禁用自动提交模式 在下面的代码中,con 是一个活动连接:

SetAutoCommit (false) ;

资料来源: JDBC 事务

JDBC 隐式地划分了在与事务的连接上执行的 每个人查询/更新。您可以通过调用 SetAutoCommit (false)来关闭自动提交模式并调用 提交()/回滚()来指示事务的结束来自定义此行为。伪密码

try
{
con.setAutoCommit(false);


//1 or more queries or updates


con.commit();
}
catch(Exception e)
{
con.rollback();
}
finally
{
con.close();
}

现在,您所显示的方法中有一个类型。它应该是 SetTransaction 隔离(int 级别),而不是用于事务划分的 API。它管理一个操作所做的更改如何/何时对其他并发操作可见,即 中的 “我”( http://en.wikipedia.org/wiki/isolation_(database_systems))

事实上,读 JDBC 教程中的这个页面会更好。
您可以获取连接,设置隔离级别,然后进行更新和操作,然后提交或回滚。

回答我自己的问题:

参见 Oracle 的 JDBC 教程

也许这能回答你的问题: 每个连接只能有一个事务。 如果自动提交处于(默认)状态,每次选择、更新、删除都会自动启动并提交(或回滚)一个事务。 如果关闭自动提交,就会启动一个“新”事务(意味着提交或回滚不会自动发生)。在某些语句之后,您可以调用提交或回滚,这将完成当前事务并自动启动一个新事务。 在纯 JDBC 上的一个 JDBC 连接上不能有两个活动打开的事务。

您可以使用以下方法进行交易:

  1. 您必须创建像 con这样的连接对象
  2. con.setAutoCommit(false);
  3. 你的疑问
  4. 如果一切都是真的
  5. 否则 con.rollback();

首先,如果你想让你的连接保持“ setAutoCommit (true)”模式,但仍然想要一个事务,你可以手动运行一个事务:

 try (Statement statement = conn.createStatement()) {
statement.execute("BEGIN");
try {
// use statement ...
statement.execute("COMMIT");
}
catch (SQLException failure) {
statement.execute("ROLLBACK");
}
}

将一个连接用于多个事务(重用、合用或链接) ,一些奇怪的问题可能潜伏在人们不得不生活的问题中,因为他们通常不能识别原因。

我想到了以下情况:

  1. (重新 -)使用连接与正在进行/未提交的事务
  2. 有缺陷的连接池实现
  3. 在一些数据库(特别是分布式 SQL 和 NoSQL)中实现更高的隔离级别

第一点直截了当,可以理解。 点2基本上导致点1或(和)点3。

第3点是关于在发出第一条语句之前已经开始了新事务的系统。从数据库的角度来看,这样的事务可能早在发出‘ first’real 语句之前就已经启动了。如果并发模型基于快照思想,即只读取事务开始时有效的状态/值,但后来没有更改,那么在提交当前事务的完整读集时也验证这一点非常重要。

由于 NoSQL 和某些隔离级别(如 MS SQL-Server Snapshot)通常不会(以正确的方式)验证读集,因此通常不会有所预期。虽然这个问题总是存在,但是当处理在最后一次提交时开始的事务或者当连接被池化而不是实际使用的连接时,情况会更糟糕,通常重要的是确保事务在预期开始时真正开始。(如果使用只回滚只读事务,也非常重要)。

在 JAVA 中处理 JDBC 时,我使用以下规则:

  1. 如果公司使用普通 JDBC 并结合使用任何池机制,那么在使用 JDBC 连接之前总是回滚该连接(取消所有内容并启动新的事务)
  2. 使用 Hibernate 进行事务处理,即使只使用会话管理的 JDBC 连接进行普通 SQL。到现在为止,从来没有过交易问题。
  3. 使用 BEGIN/COMMIT/ROLLback 作为 SQL 语句(如前所述)。如果在活动事务期间发出 BEGIN 语句,大多数实现都会失败(为数据库测试它,并记住测试数据库不是生产数据库,JDBC Driver 和 JDBC Server 端实现的行为可能与在实际服务器上运行 SQL 控制台有所不同)。
  4. 对于 JDBC 连接实例,在自己的包装器中使用3。这样事务处理总是正确的(如果没有使用反射且连接池没有缺陷的话)。

我只在响应时间关键或者 Hibernate 不可用时才使用3 + 4。 4允许在特殊情况下使用一些更高级的性能(响应时间)改进模式