Doctrine可以处理多列UNIQUE索引吗



例如,我有一个实体:

/**
* Serie
*
* @ORMTable(name="series", uniqueConstraints={@ORMUniqueConstraint(name="unique_position", columns={"chart_id", "position"})})
*/
class Serie
{
/**
* @var int
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var int
*
* @ORMColumn(name="position", type="integer")
*/
private $position;
/**
* @var Chart
*
* @ORMManyToOne(targetEntity="Chart", inversedBy="series")
* @ORMJoinColumns({
*   @ORMJoinColumn(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重新排序。

我认识到,也许没有办法指示条令执行这一操作(尤其是掉期操作(。

我是否能够添加一些"原则"听众,他们只是干预选定的案件,并执行我在没有"原则"的情况下所做的事情?

或者可能不应该使用数据库级别的唯一索引和信任原则?

一些数据库可以在事务结束时检查唯一约束。在这种情况下,ORM原则运作良好。看起来MySQL还不支持这个功能。

只有数据库本身才能可靠地强制执行唯一性。该学说对此的支持微乎其微。

解决方法是将这些操作分为两个阶段。

  1. 删除行或将位置更改为负数
  2. 将位置更改为所需的数字

在原始SQL中,将这些操作放在一个事务中很容易。你也可以为Doctrine创建监听器,但这要复杂得多。

最新更新