【问题标题】:Multiple Service Layers and Database Transactions多个服务层和数据库事务
【发布时间】:2009-10-27 21:47:01
【问题描述】:

我只是想知道如何最好地处理跨多个服务层的事务。服务层使用 ORM 从数据库中存储和检索。交易是否应该在各个服务层内被知晓和处理?还是应该由另一层处理?

例如:我有两个服务层用于用户和客户端。我想:

1) 创建并保存新客户端
2) 创建并保存新用户
3) 将该用户分配给客户端

全部在一个事务中。

一个简单的例子可能如下所示:

$userManagementService = new UserManagementService;
$newUserData = array(...);
$newUser = $userManagementService->create($newUserData);

$clientManagementService = new ClientManagementService;
$newClientData = array(...);
$newClient = $clientManagementService->create($newClientData);

$userManagementService->assignUserToClient($newUser, $newClient);

事务逻辑应该去哪里?

【问题讨论】:

    标签: php database design-patterns transactions domain-driven-design


    【解决方案1】:

    不要尝试在服务层或 ORM 中执行嵌套事务。

    事务对于数据库连接来说是全局的。除非您的 RDBMS 本身支持嵌套事务并且您的 DB API 公开嵌套事务,否则您可能会遇到异常。

    详情见我对How do detect that transaction has already been started?的回复

    由于您使用的是 PHP,因此您的事务范围至多是一个请求。所以你应该只使用容器管理的事务,而不是服务层事务。也就是说,在开始处理请求时启动事务,并在处理完请求时提交(或回滚)。

    如果需要回滚的异常发生在嵌套 ORM 操作的深处,则使用异常将其冒泡,并让容器(即您的 PHP 操作控制器)处理它。

    【讨论】:

    • 明白了,有道理。也感谢您的链接,那里有一些很好的解释。
    【解决方案2】:

    您是否面临交易聚合?这个伪代码和我想你说的相符吗?

    try
        begin application transaction
        begin ORM transaction 1
           create new user
           commit request
        begin ORM transaction 2
           create new client
           commit request
        begin ORM transaction 3
           create user client association
           commit request
        commit application tx
    catch()
        abort ORM tx 3
        abort ORM tx 2
        abort ORM tx 1
        abort app tx
    

    在任何时候,嵌套事务的回滚都可能会引发异常,并且这些异常会在逻辑上回滚two-phase commit 中的所有嵌套事务。

    我可能没有得到你想要的东西。

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 2013-05-16
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多