【问题标题】:Doctrine batch delete join table recordsDoctrine 批量删除连接表记录
【发布时间】:2013-11-04 16:18:10
【问题描述】:

我在两个实体之间有一个正常的多对多关系:用户和对象。

________        _________________        ____________
| User |        |   User_Object |        |  Object  |
|------|        |---------------|        |----------|
|  id  |        |     user_id   |        |    id    |
| .... |        |    object_id  |        |   ....   |
|______|        |_______________|        |__________|

我想批量删除相当大的用户集(以及在 User_Object 表中与它们关联的记录)。逐个删除实体不足以满足我的需求(对于 > 1000 个实体,它需要很长时间)。

//This method is far too slow for my needs
$qb = $this->doctrine->em->createQueryBuilder();
$qb->select('u')
    ->from('Entities\User', 'u')
    ->where("u.whatever= ?1")
    ->setParameter(1, $whatever);
$users = $qb->getQuery()->getResult();

foreach($users as $user)
{
    $this->doctrine->em->remove($user);
    //...

doctrine docs 说批量删除实体最有效的是 DQL,这会给我类似的信息:

$qb = $this->doctrine->em->createQuery('delete from Entities\User u where u.whatever = ?1');
$qb->setParameter(1, $whatever);
$numDeleted = $qb->execute(); //This will throw because of User_Object records

这会因为 User_Object 连接表中的记录而引发异常(参照完整性异常)。

所以,我的问题是:如何在批量删除场景中有效地删除连接表中的记录。

我真的很想避免向它抛出原始 SQL,我的其余代码到处都使用实体,如果可能的话,我希望保持这种方式。

编辑: 关系标记为这样(我使用 yml):

manyToMany:
  objects:
  targetEntity: Object
  inversedBy: users
  cascade: ["remove"]
  joinTable:
    name: User_Object
    joinColumns:
      user_id:
        referencedColumnName: id
    inverseJoinColumns:
      object_id:
        referencedColumnName: id

【问题讨论】:

    标签: php mysql doctrine-orm doctrine dql


    【解决方案1】:

    如果您要删除对象的用户,您还没有设置教义的行为。 你必须说如果用户被删除,那么所有相关的对象也必须被删除。

    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="objects", cascade={"remove"})
     */
    protected $users;
    
    
    /**
     * @ORM\ManyToMany(targetEntity="Object", inversedBy="users", cascade={"persist", "remove"})
     * @ORM\JoinTable(name="user_object",
     * joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     * inverseJoinColumns={@ORM\JoinColumn(name="object_id", referencedColumnName="id")}
     * )
     */
    protected $objects;
    

    这是一个例子。我没有测试它。

    【讨论】:

    • 关系被标记为级联删除。我已经用我的 yml 定义编辑了我的问题。我认为这就是它与 EntityManager 一起工作的原因(但不能直接与 DQL 一起工作)。那可能吗?无论如何,即使使用级联删除它也不起作用。我仍然遇到和以前一样的错误。
    • 您在用户端定义了级联删除,但没有在对象端定义。级联选项必须在反面定义,因为您要删除用户而不是对象。当您使用 DQL 删除数据库中的内容时,要通过关系继续删除,您也可以使用 onDelete 选项。 onDelete 选项用于数据库端而不是级联。 Cascade 用于内存方面。
    猜你喜欢
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多