Doctrine 可以处理多列 UNIQUE 索引吗?
Posted
技术标签:
【中文标题】Doctrine 可以处理多列 UNIQUE 索引吗?【英文标题】:Can Doctrine handle multiple column UNIQUE indexes? 【发布时间】:2020-02-21 13:40:08 【问题描述】:例如,我有一个实体:
/**
* Serie
*
* @ORM\Table(name="series", uniqueConstraints=@ORM\UniqueConstraint(name="unique_position", columns="chart_id", "position"))
*/
class Serie
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var int
*
* @ORM\Column(name="position", type="integer")
*/
private $position;
/**
* @var Chart
*
* @ORM\ManyToOne(targetEntity="Chart", inversedBy="series")
* @ORM\JoinColumns(
* @ORM\JoinColumn(name="chart_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
* )
*/
private $chart;
具有以下架构:
CREATE TABLE IF NOT EXISTS series (
id INT(11) NOT NULL AUTO_INCREMENT,
chart_id INT(11) NOT NULL,
position INT(11) NOT NULL
PRIMARY KEY (id),
UNIQUE INDEX unique_position (chart_id ASC, position ASC) VISIBLE,
UNIQUE INDEX unique_name (chart_id ASC, name ASC) VISIBLE,
INDEX IDX_582B2D4DBEF83E0A (chart_id ASC) VISIBLE,
CONSTRAINT FK_582B2D4DBEF83E0A
FOREIGN KEY (chart_id)
REFERENCES chart (id)
ON DELETE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
并使用以下数据:
|----|----------|----------|
| id | position | chart_id |
|----|----------|----------|
| . | . | . |
| . | . | . |
| 3 | 6 | 2 |
| 6 | 1 | 3 |
| 1 | 2 | 3 |
| 4 | 3 | 3 |
| 5 | 4 | 3 |
| 2 | 1 | 4 |
| . | . | . |
| . | . | . |
|----|----------|----------|
当使用对象(即不是 DQL)时,如何对 ID#3 的图表执行以下操作:
将系列 ID#1 的位置更改为 4,将系列 ID#5 的位置更改为 2? 删除系列 ID#4,然后重新排序剩余系列 ID#6、ID#1 和 ID#5 的位置,从 1、2、4 到 1、2、3?当我尝试执行 flush() 时,我得到一个唯一约束错误。
在没有 Doctrine 的情况下进行交换操作时,我将 ID#1 位置临时存储为零,将 ID#5 位置写入 ID#1 位置(不再违反唯一约束),然后将 ID#1 位置写入ID#5 位置。
在没有Doctrine的情况下进行删除操作时,我先删除ID#4,然后使用UPDATE series SET position=position-1 WHERE chart_id=3 AND position > 2
重新排序。
我认识到也许没有办法指示 Doctrine 执行此操作(尤其是交换操作)。
我是否能够添加一些 Doctrine 监听器,它只是干预选定的案例并实现我在没有 Doctrine 的情况下所做的事情?
或者也许人们不应该使用数据库级别的唯一索引并信任 Doctrine?
【问题讨论】:
可能是数据库的限制。您可以在原始 SQL 中的一个事务中进行此更改吗? @Michas 如果不使用触发器或存储过程,我不相信。与 Doctrine 一起使用时是否需要一个模式,其中所有实体修改都可以在一个事务中完成? 【参考方案1】:某些数据库可以在事务结束时检查唯一约束。在这种情况下,Doctrine ORM 可以正常工作。看来 mysql 还不支持这个功能。
只有数据库本身才能可靠地强制执行唯一性。教义对此的支持微乎其微。
解决方法是将这些操作分为两个阶段。
-
删除行或将位置更改为负数。
将位置更改为所需的数字。
在原始 SQL 中,很容易将这些操作放在一个事务中。你也可以为 Doctrine 创建监听器,但这要复杂得多。
【讨论】:
谢谢米哈斯。在事务结束时检查唯一约束是迄今为止最好的解决方案。感谢您的解决方法。以上是关于Doctrine 可以处理多列 UNIQUE 索引吗?的主要内容,如果未能解决你的问题,请参考以下文章