Существует таблица со многими столбцами, а также столбец первичного ключа «id», имеющий атрибут автоматического увеличения. База данных — mySQL.
В этот столбец вставляются два вида PHP-кода. 1.) Обычные запросы на вставку создаются в виде строки и выполняются путем подключения ADO к базе данных. В этом случае значение первичного ключа не предоставляется, поэтому используется значение автоматического увеличения таблицы.
2.) Существует класс сущности доктрины php symfony с основным полем, объявленным как
/**
* @var int
*
* @ORM\Column(name = "id", type = "integer", nullable=false)
* @ORM\Id
*/
private $id;
Вставка использует метод persist диспетчера сущностей. Здесь при вставке значение идентификатора указано явно, который намного больше, чем значение автоинкремента столбца. Вот почему Generation_Type опущен в аннотациях.
Теперь предположим, что текущее значение auto_increment равно 10000. Я хочу, чтобы при выполнении первого сценария следующий идентификатор принимался как 1001, что и ожидается. А вот в случае выполнения второго сценария с явным id=2000 вставляет запись с 2000 но не меняет auto_increment на 2000. Все равно должно остаться на 1001.
Должен ли я вносить изменения в этот фрагмент кода?
$this->em->persist(obj);
Заранее спасибо.
Итак, в системе два потока. Первый поток использует сценарий 1, который по-прежнему вставляет запросы, используя значение автоматического увеличения столбца id. Второй поток, который также является новым и использует сценарий 2, фактически является частью REST API. Клиент, который использует этот API, отправит идентификатор явно в полезной нагрузке, хотя этот идентификатор будет намного больше, чем текущее максимальное значение в столбце id. Я хочу, чтобы сценарий 1 по-прежнему использовал значение автоматического увеличения, а сценарий 2 использовал идентификатор, который он получает от своего клиента.
Я понимаю ваш вариант использования, и на самом деле это можно сделать, манипулируя метаданными класса объекта во время выполнения, НО вам абсолютно не следует этого делать! И вот почему: значение автоинкремента в mySQL не сохраняется и будет определяться при запуске базы данных путем выбора максимального значения столбца id и установки следующего значения. Я не знаю, сможете ли вы каким-либо образом обойти это, но после того, как вы вставите запись с высоким идентификатором после следующего запуска, вы столкнетесь с проблемами.
Дополнительная информация. Сброс поведения автоматического увеличения значения изменился в mySQL 5.8, поэтому в зависимости от вашей версии mysql вы можете это сделать. Вот дополнительная информация об этом изменении и возможных проблемах: benadel.com/blog/….
Я использую версию mySQL 5.8. Поскольку вы сказали, что это можно сделать, манипулируя метаданными класса объекта, не могли бы вы предоставить пример кода, чтобы я мог изучить его и сравнить различные подходы к его обработке? Кстати, спасибо за блог, которым вы поделились.
Я все еще думаю, что было бы лучше добавить столбец для «внешнего идентификатора». Было что-то похожее в старом проекте. «Это значение никогда не будет достигнуто», — сказали они. Угадай, что случилось...






Если вам не нужно, чтобы ваша сущность Doctrine когда-либо использовала стратегию AUTO для установки значения идентификатора, вы должны просто иметь возможность использовать стратегию NONE
/**
* @ORM\Column(type = "integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy = "NONE")
*/
private $id;
Дополнительную информацию о доступных стратегиях можно найти здесь: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/basic-mapping.html#identifier-generation-strategies
Если вам нужно, чтобы ваша сущность имела стратегию автоматического увеличения в обычном рабочем процессе, вы можете установить для нее значение AUTO и отключить ее в нужное время:
$metadata = $entityManager->getClassMetadata(get_class($entity));
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
$em->persist($entity);
$em->flush();
Общий отказ от ответственности: действуйте осторожно!
Я попробовал это. Проблема в том, что когда я указываю идентификатор явно, он успешно вставляет эту запись, но также изменяет значение автоматического увеличения этого столбца. Например, значение автоматического приращения равно 1000. И я вставляю запись с id = 2000. После вызова `$this->em->persist(obj); $this->em->flush(obj); ` значение автоматического увеличения изменяется на 2001, а это не то, что мне нужно.
Я предполагаю, что эта часть происходит на уровне mysql без влияния доктрины. Хорошо, я не думаю, что вы предотвратите это, пока схема объявляет поле как auto_increment. Вероятно, это можно решить только путем запроса текущего значения, вставьте доктрину и выполните запрос, чтобы сбросить значение до того, что вы получили раньше. Однако произойдет ужасный сбой, если оба потока будут вставлены одновременно. В этот момент я бы переключился на совершенно другой подход и избавился бы от этого ужасного дизайна.
Да, я согласен Этот подход может потерпеть неудачу во многих местах. Спасибо за объяснение.
должны ли $entityManager и $em быть одной и той же переменной в вашем коде?
@Джо, спасибо, чувак! Это работает для меня. В случаях, когда вам нужно, чтобы объект имел автоматически увеличивающийся идентификатор первичного ключа, но в некоторых случаях (например, автоматический импорт) вам необходимо установить идентификатор вручную, ЭТО ДОЛЖНО БЫТЬ ПРИНЯТО как правильный ответ. Спасибо чувак
И, кстати, у меня не было проблемы с увеличением идентификатора +1 - я также использую MySQL - проблема должна быть где-то еще...
почему ты хочешь сделать это? Похоже на ошибки, которые будет трудно найти через несколько месяцев