Может ли Doctrine обрабатывать несколько столбцов УНИКАЛЬНЫХ индексов? - PullRequest
0 голосов
/ 21 февраля 2020

Например, у меня есть объект:

/**
 * 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), как можно выполнить следующие действия для диаграммы с идентификатором №3:

  • Изменить позицию идентификатора серии № 1 на 4 и позицию идентификатора серии № 5 на 2?
  • Удалить серийный номер № 4, а затем изменить порядок, оставив серийный номер № 6, идентификатор № 1 и позицию № № 5 с позициями 1, 2, 4 до 1, 2, 3?

Когда я при попытке выполнить flu sh () я получаю уникальную ошибку ограничения.

При выполнении операции подкачки без Doctrine я временно сохраняю позицию ID # 1 как ноль, записываю позицию ID # 5 в ID Положение # 1 (которое больше не нарушает уникальное ограничение), а затем записать положение идентификатора № 1 в положение идентификатора № 5.

При выполнении операции удаления без Doctrine я сначала удаляю идентификатор № 4 и затем измените порядок, используя UPDATE series SET position=position-1 WHERE chart_id=3 AND position > 2.

. Я понимаю, что, возможно, нет способа указать Doctrine, чтобы выполнить это (особенно операции подкачки). on).

Могу ли я добавить некоторый Doctrine слушатель, который просто вмешивается в отдельные случаи и реализует то, что я делал без Doctrine?

Или, возможно, следует просто не использовать базу данных Уровень уникальных индексов и доверия Doctrine?

1 Ответ

1 голос
/ 22 февраля 2020

Некоторые базы данных могут проверять уникальные ограничения в конце транзакции. В этом случае Doctrine ORM работает нормально. Похоже, MySQL пока не поддерживает эту функцию.

Только сама база данных может надежно обеспечивать уникальность. Поддержка этого в Doctrine минимальна.

Обходной путь может заключаться в разделении этих операций на две фазы.

  1. Удаление строк или изменение позиций на отрицательные числа.
  2. Изменить позиции на нужные числа.

В необработанном виде SQL эти операции легко поместить в одну транзакцию. Вы можете создать слушатель для Doctrine, чтобы сделать это тоже, но это намного сложнее.

...