【问题标题】:Should my Service implements transaction & commit method?我的服务应该实现事务和提交方法吗?
【发布时间】:2011-08-25 16:01:58
【问题描述】:

假设我想在我的UsersController 中进行批量用户更新。

在我的UsersController 我愿意:

foreach ($users as $user) {
    $userService = new UserService();
    $user->updateUser($data);
}

如果有很多用户,它可能会变慢,因为 UserService::updateUser 方法只是执行persist()/flush()

所以我想知道这样做是否是个好主意:

class UserService {
  public function setUseTransaction($flag)
  {
      $this->useTransaction = $flag;
      return $this;
  }

  public function updateUser($data)
  {
     // some data mapping

     $entityManager->persist($user);

     if ($this->useTransaction) {
       $entityManager->flush();
     }
   }

   public function commit()
   {
      $entityManager->flush();
   }
}

然后在我的UsersController 我可以做到:

$userService = new UserService();
$userService->setUseTransaction(true);

foreach ($users as $user) {
    $userService = new UserService();
    $user->updateUser($data);
}

$userService->commit();

你有什么想法?

【问题讨论】:

    标签: php zend-framework design-patterns doctrine-orm service-layer


    【解决方案1】:

    我不想在我的服务层之上公开任何事务管理的东西。我可能会将所有这些东西都推到我的服务中,并公开两个公共方法 updateUser(userEntity) (用于一次性使用隐式刷新)和 updateUsers(array-of-users) (用于批量更新)

    大概是这样的:

    class UserService {
    
        public function updateUser(User $user){
            $this->_updateUser();
            $this->em()->flush();        
        }
    
        public function updateUsers(array $users){
            foreach($users as $u) $this->_updateUser($u);
            $this->em()->flush();     
        }
    
        private function _updateUser(User $user){
            //do stuff to $user
            $this->em()->persist($user);
        }
    }
    

    然后,如果您稍后决定要将更新分块为 100 个或其他组,那么您的所有批量更新逻辑都很好地考虑在服务中,而不是在控制器中可能存在多个位置。

    【讨论】:

    • 简单而聪明,我不知道为什么我以前没有考虑过:)
    • 如果 updateUser() 执行了实际上是提交的 flush(),如果您的 updateUser( ) 里面有一个 flush() 吗?
    • @peufeu - 您只需在一些适当的服务类中编写一个方法即可。
    【解决方案2】:

    将其全部包装在事务中肯定会加快速度。

    不过,将整个批量更新编写为单个 SQL 查询会快数百倍。

    【讨论】:

    • 我的问题可能不清楚,我知道事务会加速我的应用程序,但是,我想知道在我的服务中耦合这样的操作是否是个好主意,它几乎表示我的 Service 正在使用数据库,但实际上,这不是 Service Layer 的目的,还是谢谢您
    • @JohnT - 不,您的服务正在与 EM 合作,它也应该如此。关于何时刷新()的选择可能在您的服务中而不是在某些控制器中更好。请参阅我的答案以了解更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多