Я пишу конвертор для конвертирования записей из старой БД в новую с использованием Symfony и
A2lixI18nDoctrineBundle
В старой БД в одной таблице хранились названия на двух языках. Теперь будет использоваться одна таблица для хранения дерева категорий и вторая таблица для названий категорий на двух языках. Проблема в следующем: мне нужно вставлять в БД с помощью Doctrine элементы с уже установленными ID. Это я решил с помощью следующего кода:
$classMetadata = $this->getClassMetadata($entity);
$classMetadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
$classMetadata->setIdGenerator(new AssignedGenerator());
Таким образом я могу сейчас устанавливать свои айдишки. Но после этого мне нужно чтобы новые категории добавлялись с генерацией новых ID, которые не должны пересекаться с существующими. Я не очень хочу самостоятельно для всех моделей генерировать ID как минимум из-за того, что будут лишние запросы к БД. Их будет не много, но, по-хорошему, их стоило бы не делать. Так вот, когда у меня была лишь одна таблица и с ней ничего связано не было (таблица локализированных записей) я делал следующее:
1. Таблица для категорий генерировалась изначально с AUTO_INCREMENT
2. Перед тем, как начать конвертирование категорий я убирал из таблицы AUTO_INCREMENT и вышеуказанным кодом изменял стратегию генерации ID для этой модели.
3. Конвертировал записи, добавлял их в таблицу
4. После конвертации категорий я создавал новую таблицу со структурой таблицы категорий (1), добавлял AUTO_INCREMENT для ID (2), устанавливал значение AUTO_INCREMENT для новой таблицы значение {MAX_CATEGORY_ID + 1} (3), переносил конвертированные записи со старой таблицы в новую (4), удалял прежнюю таблицу (5), переименовывал новую таблицу в старую.
private function setAutoincrementValue($entity, $autoincrement)
{
$tableName = $this->getClassMetadata($entity)->getTableName();
$tableNameNew = $tableName.'_new';
$this->getEntityManager()->getConnection()
->exec(
"DROP TABLE IF EXISTS `{$tableNameNew}`;
CREATE TABLE `{$tableNameNew}` LIKE `{$tableName}`;
ALTER TABLE `{$tableNameNew}` CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `{$tableNameNew}` AUTO_INCREMENT = {$autoincrement};
INSERT INTO `{$tableNameNew}` SELECT * FROM {$tableName};
DROP TABLE `{$tableName}`;
RENAME TABLE `{$tableNameNew}` TO `{$tableName}`;"
);
}
Это решение работало пока я не добавил локализацию для категорий и не вынес ее в отдельную таблицу.
Я пробовал сперва установить AUTO_INCREMENT в значение, которое превышает max(ID) категорий и установить стратегию генерации ID в доктрине на ручную (при этом в таблице был установлен AUTO_INCREMENT для ключа), но тогда вылетала ошибка
здесь.
Если же установать значение AUTO_INCREMENT, но не изменять стратегию генерации ID, то все значения вставятся с ID, которое превышает устанавливаемое значение AUTO_INCREMENT
Я предполагаю, что эта проблема вылезла бы и потом - когда я начну добавлять контент к категориям - он будет привязан к категориям и будут использоваться ключи для связи.
Теперь собираю все вместе и формирую результирующий вопрос: каким путем идти чтобы можно было корректно вставлять записи в таблицу с предустановленными ключами и записями в связанную таблицу внешним ключом и в последствии иметь возможность пользоваться AUTO_INCREMENT для первичного ключа таблицы?
Возможно, я что-то не так сформировал - в комментариях отвечу на вопросы.
UPDATE
на сколько я понимаю, то более чистым и правильным решением будет создание собственного ID-генератора (который будет генерировать ID как {max(id_on_table) + 1} если у сущности не установлен ID и возвращать ID сужности, если установлен) и использовать его для конвертируемых моделей