简体   繁体   English

多个服务层和数据库事务

[英]Multiple Service Layers and Database Transactions

I'm just wondering how to best handle transactions across multiple service layers. 我只是想知道如何最好地处理跨多个服务层的事务。 The service layers use an ORM to store and retrieve from the database. 服务层使用ORM来存储和从数据库中检索。 Should the transactions be known and handled within the individual service layers? 是否应该在各个服务层内知道和处理交易? Or should they be handled by another layer? 或者它们应该由另一层处理?

For example: I have two service layers for users and clients. 例如:我有两个服务层供用户和客户使用。 I would like to: 我想要:

1) Create and save a new client 1)创建并保存新客户端
2) Create and save a new user 2)创建并保存新用户
3) Assign that user to the client 3)将该用户分配给客户端

All within a single transaction. 所有这些都在一次交易中。

A simple example might look like this: 一个简单的例子可能如下所示:

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

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

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

Where should transaction logic go? 交易逻辑应该在哪里?

Do not try to do nested transactions within service layers or within the ORM. 不要尝试在服务层或ORM中执行嵌套事务。

Transactions are global to the DB connection. 事务是数据库连接的全局事务。 Unless your RDBMS supports nested transactions natively and your DB API exposes nested transactions, you can run into anomalies. 除非您的RDBMS本身支持嵌套事务, 并且您的DB API公开嵌套事务,否则您可能会遇到异常。

For details, see my answer to How do detect that transaction has already been started? 有关详细信息,请参阅我如何检测事务已启动的答案

Since you're using PHP, the scope of your transactions is at most a single request. 由于您使用的是PHP,因此您的交易范围最多只是一个请求。 So you should just use container-managed transactions, not service-layer transa. 所以你应该只使用容器管理的事务,而不是服务层transa。 That is, start the transaction at the start of handling the request, and commit (or rollback) as you finish handling the request. 也就是说,在处理请求开始时启动事务,并在完成处理请求时提交(或回滚)。

If an exception requiring a rollback occurs deep within nested ORM actions, then bubble that up by using an Exception, and let the container (ie your PHP action controller) take care of it. 如果需要回滚的异常发生在嵌套的ORM操作中,那么请使用Exception将其冒泡,然后让容器(即您的PHP操作控制器)处理它。

Are you facing an aggregation of transactions? 您是否面临交易聚合? Does this pseudo code match what I think you're saying? 这个伪代码是否符合我的想法?

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

At any point a rollback of a nested transaction will likely throw an exception, and those exceptions would logically roll back all the nested transactions in the two-phase commit . 在任何时候,嵌套事务的回滚都可能引发异常,并且这些异常将在逻辑上回滚两阶段提交中的所有嵌套事务。

I might not be getting what you're after tho. 我可能没有得到你之后的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM