내 엔터티는 ID에이 주석을 사용합니다.
/**
* @orm:Id
* @orm:Column(type="integer")
* @orm:GeneratedValue(strategy="AUTO")
*/
protected $id;
깨끗한 데이터베이스에서 이전 데이터베이스의 기존 레코드를 가져와 동일한 ID를 유지하려고합니다. 그런 다음 새 레코드를 추가 할 때 MySQL이 평소와 같이 ID 열을 자동으로 늘리기를 원합니다.
불행히도 Doctrine2는 지정된 ID를 완전히 무시하는 것으로 보입니다.
새로운 솔루션
아래 권장 사항에 따라 다음이 선호되는 솔루션입니다.
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
오래된 솔루션
Doctrine은 생성기 전략을 결정하기 위해 ClassMetaData에서 피벗되므로 EntityManager에서 엔티티를 관리 한 후 수정해야합니다.
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$this->em->flush();
방금 MySQL에서 테스트했으며 예상대로 작동했습니다. 즉, 사용자 지정 ID가있는 엔터티는 해당 ID로 저장되고 지정된 ID가없는 엔터티는 lastGeneratedId() + 1
.
답변
귀하의 솔루션은 MySQL에서 잘 작동하지만 시퀀스 기반이므로 PostgreSQL에서 작동하도록 만들지 못했습니다.
완벽하게 작동하도록이 줄을 추가해야합니다.
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
친애하는,
답변
아마도 교리가 바뀌었지만 이제 올바른 방법은 다음과 같습니다.
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
답변
엔터티가 클래스 테이블 상속의 일부인 경우 두 엔터티 (지속중인 엔터티 및 루트 엔터티) 에 대한 클래스 메타 데이터에서 id-generator를 변경해야합니다.
답변
새 솔루션은 모든 엔티티가 삽입 전에 ID가있는 경우에만 제대로 작동합니다. 한 엔터티에 ID가 있고 다른 엔터티에는없는 경우 새 솔루션이 실패합니다.
이 기능을 사용하여 모든 데이터를 가져옵니다.
function createEntity(\Doctrine\ORM\EntityManager $em, $entity, $id = null)
{
$className = get_class($entity);
if ($id) {
$idRef = new \ReflectionProperty($className, "id");
$idRef->setAccessible(true);
$idRef->setValue($entity, $id);
$metadata = $em->getClassMetadata($className);
/** @var \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata */
$generator = $metadata->idGenerator;
$generatorType = $metadata->generatorType;
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$unitOfWork = $em->getUnitOfWork();
$persistersRef = new \ReflectionProperty($unitOfWork, "persisters");
$persistersRef->setAccessible(true);
$persisters = $persistersRef->getValue($unitOfWork);
unset($persisters[$className]);
$persistersRef->setValue($unitOfWork, $persisters);
$em->persist($entity);
$em->flush();
$idRef->setAccessible(false);
$metadata->setIdGenerator($generator);
$metadata->setIdGeneratorType($generatorType);
$persisters = $persistersRef->getValue($unitOfWork);
unset($persisters[$className]);
$persistersRef->setValue($unitOfWork, $persisters);
$persistersRef->setAccessible(false);
} else {
$em->persist($entity);
$em->flush();
}
}
답변
Doctrine 2.5 및 MySQL 용 솔루션
“새로운 솔루션”은 Doctrine 2.5 및 MySQL에서 작동하지 않습니다. 다음을 사용해야합니다.
$metadata = $this->getEntityManager()->getClassMetaData(Entity::class);
$metadata->setIdGenerator(new AssignedGenerator());
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
그러나 아직 다른 DBMS를 시도하지 않았기 때문에 MySQL에 대해서만 확인할 수 있습니다.
답변
Doctrine 엔티티에 대한 향후 ID를 설정 하는 라이브러리 를 만들었습니다 . 영향을 최소화하기 위해 대기중인 모든 ID가 소비되면 원래 ID 생성 전략으로 되돌아갑니다. 이와 같은 코드를 반복 할 필요가 없도록 단위 테스트를위한 쉬운 드롭 인이어야합니다.
답변
Villermen 작업에서 영감을 받아 , 엔티티가 AUTO, SEQUENCE, IDENTITY 또는 UUID 상태를 사용하는 경우에도 Doctrine 엔티티에 ID를 수동으로 할당 할 수 있는 라이브러리 tseho / doctrine-assigned-identity 를 만들었습니다 .
당신은 생산에 사용해서는 안 하지만, 기능 테스트 정말 유용합니다.
라이브러리는 할당 된 ID가있는 엔티티를 자동으로 감지하고 필요한 경우에만 생성기를 교체합니다. 인스턴스에 할당 된 ID가없는 경우 라이브러리는 초기 생성기를 대체합니다.
생성기 교체는 Doctrine EventListener에서 발생하므로 조명기에 추가 코드를 추가 할 필요가 없습니다.