2011-03-07 52 views
0

我了解交易工作,一切功能如何预期,但我不喜欢我访问连接提交或者回滚事务的方式。什么是要访问一个事务提交或回滚的首选方式?

我有3个服务类可以访问相同的单身连接对象。我想在一个事务中来包装这三样东西,所以我这样做:

try { 
    $service1 = new ServiceOne; 
    $service2 = new ServiceTwo; 
    $service3 = new ServiceThree; 

    $service1->insertRec1($data); 
    $service2->deleteRec2($data); 
    $service3->updateRec3($data); 

    $service1->getSingletonConnection()->commit(); 
} 
catch(Exception $ex) { 
    $service1->getSingletonConnection()->rollback(); 
} 

通过getSingletonConnection返回的连接对象只是周围的OCI8连接的包装,并承诺是oci_commit;回滚是oci_rollback

正如我所说,这是可行的,因为他们都访问相同的连接,但通过任意的服务对象访问连接感觉不对。另外,还有一些在我的应用程序中使用两个不同的数据库,所以我需要确保我检索并提交正确的......不知道是否有周围,虽然任何方式。

有没有更好的方式来处理交易?

回答

2

感到不对劲访问通过任意 服务对象的 连接。

我同意你的100%。

在我看来,如果每个服务只构成数据库事务的一部分,那么服务不能直接负责确定要使用的数据库会话。您应该在定义事务的代码级别选择和管理连接。

所以你当前的代码将被修改为类似:

try { 
    $conn = getSingletonConnection(); 
    $service1 = new ServiceOne($conn); 
    $service2 = new ServiceTwo($conn); 
    $service3 = new ServiceThree($conn); 

    $service1->insertRec1($data); 
    $service2->deleteRec2($data); 
    $service3->updateRec3($data); 

    $conn->commit(); 
} 
catch(Exception $ex) { 
    $conn->rollback(); 
} 

看起来这将简化处理你的两个数据库的问题,因为只会有一个地方来决定使用哪种连接,并且您将持有对该连接的直接引用,直到您结束交易。

如果你想从单身连接扩展到连接池,这将是我能想到的唯一方法,以保证所有三个服务调用使用相同的连接。

+0

我完全同意,不过,如果你传递的是对象,你甚至可能会考虑完全干涉“Singleton”实现。 – 2011-03-08 15:04:56

1

单个连接没有任何内在错误。 如果您有多个连接,那么每个运行独立的交易。你基本上有两种选择。

  • 维护用于每个 三个服务的当前单 连接对象
  • 维护单独 的连接(与有关开销) 为每个服务,并提交/回滚 每个单独的连接分别 (没有特别安全,因为你无法保证ACID一致性 那么)

作为一种方式rou第二,你连接到两个独立的数据库实例:使用DB链接,这样你只能连接到一个单一的数据库

相关问题