【发布时间】:2020-09-28 18:39:40
【问题描述】:
我正在通过学说实体管理器导入一种 csv 数据,但是,我有一个执行批处理的循环,正如在文档级别提到的那样。 https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/batch-processing.html#bulk-inserts
$validationErrors = [];
foreach($data as $itrationNumber => $item) {
/** @var User|null $user **/
$user = $this->em->getRepository(User::class)->findOnBy(['email' => $item['email']]);
$user = ($user) ? $user : new User();
$user->setName('test');
$errors = $this->validator->validate($user);
if ($errors->count() === 0) {
$this->persist($user);
} else {
$validationErrors[] = $errors;
}
if ($itratioNumber% 100 === 0) {
$this->em->flush();
}
}
return $validationErrors;
这是我的 User 类,它对电子邮件字段有一个独特的约束:
/**
* @ORM\Entity
* @UniqueEntity("email")
*/
class User
{
/**
* @ORM\Column(name="email", type="string", length=255, unique=true)
* @Assert\Email
*/
protected $email;
}
不幸的是,如果我的数据中有不止一行具有相同的电子邮件地址,UniqueEntity 验证将不会被触发,原因很简单,因为用户被持久化但没有被刷新到数据库中。
- 解决方案 1:避免批处理并在每次迭代时执行刷新,这非常违反并且可能引发连接关闭原则或某种内存泄漏。
- 解决方案 2:创建一个自定义约束,其灵感来自
UniqueEntity("email"),然后检查每个项目的电子邮件地址,如果有用户已经使用相同的邮件。
如果用户已经存在于数据库中,并且我们调用
em-> persist(),我在$entityManager->getUnitOfWork()->getScheduledEntityInsertions()和$entityManager->getUnitOfWork()->getScheduledEntityUpdates()中都找不到任何持久对象。
仅在新插入期间,我洞对象在函数->getScheduledEntityInsertions()的响应中持续存在
如果有人知道如何在$entityManager->persist() 步骤之后恢复实体,我将不胜感激。
或者只是第三种解决方案,即使在批处理上下文中,我也可以触发对电子邮件唯一性的验证。
【问题讨论】:
-
您是否尝试过使用
em->contains($user)?参考:stackoverflow.com/questions/17613684/… -
你可能想多了。只需在保留新实体时维护一份电子邮件列表,并在添加新实体之前检查该列表。
-
@Cerad 是否有适当的方法将该列表传递给我的验证者,我想我会使用会话!
-
为什么需要会话数据?您确实必须为每个请求刷新,这将重新开始。或者也许我只是在考虑。