Let's say I want to do a bulk User update in my UsersController
.
In my UsersController
I do:
foreach ($users as $user) {
$userService = new UserService();
$user->updateUser($data);
}
If there are a lot of users, it can get slower because the UserService::updateUser method just do a persist()
/flush()
So I'm wondering if it could be a good idea to do something like that:
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();
}
开发者_StackOverflow}
Then in my UsersController
I can do:
$userService = new UserService();
$userService->setUseTransaction(true);
foreach ($users as $user) {
$userService = new UserService();
$user->updateUser($data);
}
$userService->commit();
What are your thought?
I wouldn't want to expose any transaction-management stuff above my service layer. I'd probably shove all of that stuff down into my service, and expose two public methods updateUser(userEntity) (for a one-off with an implicit flush), and updateUsers(array-of-users) (for batch updates)
Something roughly like:
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);
}
}
Then, if you later decide you want to chunk your updates into groups of 100, or whatever, all your bulk-update logic is nicely factored in the service, instead of in potentially multiple places in your controller(s).
Wrapping it all in a transaction will definitely speed things up.
Writing the whole bulk update as a single SQL query will be hundreds of times faster though.
精彩评论