我的问题是EntityManager的flush方法正在将persist方法缓冲的所有操作写入数据库。没问题,但有时更改会在我不知情的情况下在其他上下文中写入。让我给你举个例子:
class ServiceA{
public function __construct(private UserRepository $userRepository){}
public function foo(){
$user = $this->userRepository->find(1);
$user->setName('newName');
$this-userRepository->add($user, true); // second argument means that I do flush
}
}
class ServiceB{
public function __construct(
private VisitRepository $visitRepository,
private ServiceA $serviceA
){}
public function bar(){
$visit = $this->visitRepository->find(2);
$visit->setSomething(2);
$this->visitRepository->add($visit, false); // second argument means that I don't want to flush
// Some other SELECTS here via the visitRepository, usage of setters and the persist method, but without flushing
$this->serviceA->foo(); // Inside here the previous persisted instances in this context got flushed by the UserRepository's add method.
$this->visitRepository->flush() // wrapper of EntityManager's flush method. which did not flush anything.
}
}
Repository的add方法是EntityManager的persist和可选的flush的包装。像这样:
public function add(Visit $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
然后,在我的示例中,注入 EntityManager 或存储库来持久化和刷新并不重要。 所以,问题是 EntityManager(在存储库内,或者即使它作为 ServiceA 或 ServiceB 中的 EntityManager 注入)刷新所有内容,那么我的问题是,有时深层服务会刷新在我的应用程序的其他层中完成的更改,而无需我注意到。到目前为止,这对我来说还不是问题,但我可以在这里看到一个设计问题(在我这边)。
您如何解决这个问题?您有什么设计想法可以应用来解决这个问题吗?或者,有什么方法可以只将某些操作包装在刷新方法中,以便它只在数据库中写入上下文的操作?
我想像这样的解决方案来准确实体刷新的操作:
$otherContextEntityManager->persist($bar);
$thisContextEntityManager->persist($something)
$thisContextEntityManager->persist($foo);
$thisContextEntityManager->flush(); // Only $something and $foo get written in the DB
$otherContextEntityManager->persist($james);
$otherContextEntityManager->flush(); // Only $bar and $james get written in the DB.
也许将一些 EntityManager 作为非共享服务?
Doctrine 的 EntityManager 刷新当前工作单元内托管实体的所有更改。
分离要从刷新中排除的实体 $this->entityManager->detach($entity);
注意:不要将分离的对象传递给持久操作。