我正在从excel文件导入用户。我创建了实体经理:
$em = $this->getDoctrine()->getManager();
这是我的循环:
...
for ($i=2; $i<=count($usersdatas); $i++) { // $userdatas: an array of users imported from excel
$nuser = new User();
$nuser->setEmail($usersdatas[$i]['A']); // email is unique in db
$nuser->setFname($usersdatas[$i]['B']);
$nuser->setLname($usersdatas[$i]['C']);
$nuser->addChannel($channel); //ManytoMany relation
$em->persist($nuser);
$em->flush();
}
...
- 电子邮件字段在数据库中是唯一的,我不想在刷新前检查重复项(数据库验证)
- 由于日志原因,我想逐个刷新(而不是批量插入)
- 我的所有其他代码和文件(实体、服务、配置…)都是正确的,没有错误
第一个问题是,如果其中一行的电子邮件存在于数据库中(重复),则循环会被数据库中的异常打断。我用这个简单的改变解决了这个问题:
...
try {
$em->persist($nuser);
$em->flush();
} catch (Exception $e) {
...
}
...
下一个问题是"EntityManager已关闭"异常。如果一封电子邮件重复,EntityManager($em)将自动关闭。我已经通过在try/catch之前创建$em解决了这个问题:
...
if (!$em->isOpen()) {
$em = $em->create(
$em->getConnection(), $em->getConfiguration());
}
...
一切都很好。但我有一个大问题,添加信道到用户:
...
$nuser->addChannel($channel); //ManytoMany relation
...
$channel不是一个新频道。但在关闭并创建EntityManager后,系统认为它是新的在线持久化(如果没有错误,$channel将成功添加):
ORMInvalidArgumentException {#1400 ▼
#message: "A new entity was found through the relationship 'MyUserBundleEntityUser#channels' that was not configured to cascade persist operations for entity: MyPostBundleEntityChannel@000000002768057d0000000046371762. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'MyPostBundleEntityChannel#__toString()' to get a clue."
#code: 0
#file: "...vendordoctrineormlibDoctrineORMORMInvalidArgumentException.php"
#line: 91
-trace: array:13 [▶]
}
我所有的问题都来自于重新创建EntityManager。我认为这是个错误。验证数据库端的数据(唯一、Null、外键…)是常见的。在数据库出现错误后关闭EntityManager意味着我们在出现任何错误后都无法与数据库通信。
我有两个问题:
- 有什么方法可以阻止EntityManager关闭吗
- 我可以使用DBAL原则导入我的用户吗?(用户可能有重复的电子邮件)
异常适用于特殊情况。它们的设计目的是让你清理,然后返回一个友好的错误。它们不是为验证而设计的。
你在这里使用它们的方式是说"有可能添加这个用户吗?"如果没有,请重新启动数据库。也就是说,阻止实体管理器管理器抛出异常,而不是在抛出异常后继续执行。
因此,如果您在尝试添加重复用户时发现实体管理器正在抛出异常并关闭,请在尝试添加用户之前检查该用户是否为重复用户。
但是,您在上面说过,您不想使用这种方法。在这种情况下,您将需要编写自己的SQL查询,并且可以使用DBAL(或仅使用原始PDO)并自己处理SQL响应。