jdbc事务管理:释放资源和分布式事务时

时间:2010-10-05 10:29:04

标签: java jdbc transactions

您好 我是初学java开发人员,这是我发布的列表中的一个问题,因为我已经开始移植一个非常古老的Web服务。我正在尝试改进对数据库的访问,我发现很多代码我认为migth是危险的,但是对java不太熟悉我无法确定。 实际上我有一个管理数据库连接并保存对连接和语句对象的静态引用的类:它公开了一个初始化sql连接类成员变量的“openDb”方法。

问题1:类成员变量是静态的,如果多次调用openDb并且该类的第一个(例如)实例仍在执行查询,会发生什么?

上面的类公开了一个方法名“closeDb”,它释放所有资源(连接和语句都是静态成员!)和一个只释放语句成员的“closeStatement”方法,并在外部使用。

问题2:在事务提交/回滚后必须关闭stements和resultset,还是可以立即关闭?

仍然是同一个类处理提交/回滚暴露一些方法(将autocommit设置为false,提交或回滚)。此类的实例将传递给其他类实例(例如,通常的员工部门类),它们在db上执行自己的查询,最后由连接管理器类调用commit / rollback。这个“建筑”是正确的还是你认为它有任何危险?

提前谢谢

1 个答案:

答案 0 :(得分:0)

这是一个非常错误的设计,您对静态变量的观察是正确的。如果一个线程调用openDb而另一个线程执行相同的操作,那么事情就会出错。也许这种情况并非一直发生,这使得调试变得困难。

关于问题nr。 2:一旦完成它们,你应该关闭它们。这样就不会让资源占用不必要了。因此,当您从结果集中读取所有(必要的)数据时,请将其关闭。让语句和结果集逃避事务边界也不是一个好主意。所以而不是:

begin transaction
  open result set
commit transaction
read from result set

你应该:

begin transaction
  open result set
  read from result set
commit transaction

要使图片完整,使用交易时应始终具有以下模式:

begin transaction
  open connection
    read/modify data
  close connection
commit transaction

open connection / close connection组合可能会在一次交易中多次出现。

编辑:更多地完成图片:在通常情况下,您的应用程序有多个层(例如UI,业务,数据)。事务通常在业务层内启动和提交。在业务层中,您可以调用一个或多个数据层方法,这些方法将成为事务的一部分:

// Inside business layer:
public void businessMethod(...) {
    try {
        // Begin transaction.
        dataMethod1(...);
        dataMethod2(...);
        ...
        // Commit transaction.
    }
    catch (...) {
    }
}

// Inside data layer.
public void dataMethod1(...) {
    // Open connection.
    try {
        // Get data from database.
        // Manipulate data.
    }
    finally {
        // Close connection.
    }
}

一些补充说明:

  • 事务提交是try / catch中的最终语句(如果要从方法返回数据,则可以后跟return语句)。这可确保事务仅在所有都正常时提交(即不会抛出异常)。
  • 连接关闭位于try语句的finally部分内。无论数据方法中发生什么,这都可以确保它始终处于关闭状态。