对于多对多关系(比如组和用户),只要删除了任一实体,就会自动删除联合表中的行,就像为关系设置了级联删除属性一样。所以基本上我想删除它如果它只是空的。所以解决方案必须保证不会丢弃任何关系(就像FK约束保证它一样)。
默认情况下是否可以不执行此操作并在外键约束违反时抛出异常?
PS:删除之前的检查不是解决方案,因为它很容易出现竞争条件。
PPS:映射定义很简单,为了完整起见,我在这里发布它们(即使它们没有带来任何有用的东西)
PPPS:onDelete: cascade
也不是解决方案:它在数据库级别创建相应的ON DELETE CASCADE
。
PPPPS:ON DELETE RESTRICT
无法使用,因为doctrine将删除联合表中的所有引用。
角色:
manyToMany:
users:
targetEntity: UserAccount
mappedBy: roles
在用户中:
manyToMany:
roles:
targetEntity: Role
joinTable:
name: user_role
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
role_id:
referencedColumnName: id
答案 0 :(得分:2)
This answer can be considered as a workaround. The many-to-many
association can be replaced by one-to-many/many-to-one
associations between the 3 participating classes, because Doctrine has no cascade deleting with one-to-many
by default.
答案 1 :(得分:0)
几个小时前我遇到了同样的问题:
我在ManyToMany
和User
个实体之间有一个简单的Group
关联。
如果有一些相关Group
,我不希望Doctrine删除users
实体,而我希望Doctrine删除User
,即使它在某个组中也是如此。
为了实现这一点,在Group
实体中我有这行代码:
/**
* Group
*
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
*
*/
class Group
{
...
/**
* @var \Doctrine\Common\Collections\ArrayCollection
*
* @ORM\ManyToMany(targetEntity="User", mappedBy="groups")
*
*/
private $users;
...
/**
* @ORM\PreRemove()
*/
public function preRemove() {
if ($this->users->count()>0) {
throw new \AppBundle\Utils\Exception\FKConstraintViolationException();
}
}
}
这是FKConstraintViolationException类
namespace AppBundle\Utils\Exception;
class FKConstraintViolationException extends \Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException {
public function __construct() {
$message='Self generated exception';
$driverException=new \Doctrine\DBAL\Driver\OCI8\OCI8Exception('Self generated exception.'); //or whatever driver you use if you have another db
parent::__construct($message, $driverException);
}
}
在控制器中我将remove()
放在try/catch
块
try {
$em->remove($group);
$em->flush();
$this->addFlash('success', 'deleted_successfully');
} catch (\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException $e) {
$this->addFlash('error', 'cannotdelete_related_entities');
}
也许最好在preFlush
或onFlush
事件上创建一个监听器,因为你实际上可以在一个对象上调用remove()
而不会刷新,你会得到异常。