A(){
con.begin;
.........
.........
B();
........
........(con.rollback;)
con.commit;
}
B{
con.begin;
.......
.......
con.commit;
}在上面的代码中,我在A()处开始了一个新的DB事务。它成功地执行了一些事务。之后,B()开始执行,它还成功地执行了一些事务,现在控制返回到A()。在这一点上发生了一些异常,我做了一个回滚。我想知道在B()中成功的事务是否回滚。
发布于 2010-09-24 20:03:05
简而言之,不是。长长的答案如下。
Java中对嵌套事务的支持取决于各种变量的作用。
支持JTA中的嵌套事务
首先也是最重要的是,如果您使用的是JTA,则由事务管理器来支持嵌套事务。如果试图在已经与事务相关联的线程中启动新事务,则任何开始事务的尝试都可能导致事务管理器(不支持嵌套事务)抛出NotSupportedException。
来自Java Transaction API 1.1规范:
3.2.1启动事务
TransactionManager.begin方法启动一个全局事务,并将事务上下文与调用线程相关联。如果事务管理器实现不支持嵌套事务,则当调用线程已经与事务关联时,TransactionManager.begin方法将抛出NotSupportedException。
支持JDBC中的嵌套事务
JDBC3.0引入了Savepoint类,它或多或少类似于数据库中的保存点的概念。必须使用Connection.setSavepoint()方法初始化保存点,该方法返回一个保存点实例。可以使用Connection.rollback(Savepoint svpt)方法在稍后的时间点回滚到此保存点。当然,所有这些都取决于您使用的是否是支持设置保存点和回滚到保存点的JDBC 3.0兼容驱动程序。
自动提交的影响
默认情况下,所有获得的连接都被设置为自动提交,除非JDBC驱动程序在这方面有明显的偏差。如果启用此功能,则会自动排除具有嵌套事务的范围,因为通过连接在数据库中所做的所有更改都会在执行时自动提交。
如果禁用自动提交功能,并选择显式提交和回滚事务,则提交事务将始终提交连接在该时间点之前执行的所有更改。请注意,选择提交的更改不能由程序员定义-在选择提交之前的所有更改,无论它们是在一种方法中执行的还是在另一种方法中执行的。唯一的解决办法是定义保存点,或者绕过JDBC驱动程序--驱动程序通常提交与线程关联的连接执行的所有更改,因此启动一个新线程(这很糟糕)并在其中获得一个新连接,通常会为您提供一个新的事务上下文。
您可能还希望检查您的框架如何提供对嵌套事务的支持,特别是在您与JDBC API隔离或独立启动新JTA事务的情况下。
根据上面对嵌套事务支持在各种场景中如何实现的描述,代码中的回滚似乎将回滚与Connection对象关联的所有更改。
发布于 2010-09-24 19:30:37
我担心这看起来像是糟糕的事务管理。如果您改为处理从调用方到A和B的提交和回滚,那将是很好的。
A()
{
//business code A
B();
//more business code A
}
B()
{
//business code B
}
DoA()
{
try
{
con.begin();
A();
con.commit();
}
catch(Exception e)
{
con.rollback();
}
}
DoB()
{
try
{
con.begin();
B();
con.commit();
}
catch(Exception e)
{
con.rollback();
}
}发布于 2010-09-24 19:45:08
根据您的代码,在A()中,您正在启动事务。然后跳转到B(),在B()中再次启动事务,这将提交所有先前的事务。然后在B()结束时,事务被显式提交。此时,您的所有代码都已提交。现在,代码返回到A(),并处理剩余的代码。如果出现异常,只会回滚B()调用后的这一部分。
https://stackoverflow.com/questions/3786568
复制相似问题