이것이 제가 "The EntityManager is closed"라는 교리를 해결 한 방법 입니다. 발행물. 기본적으로 예외 (예 : 중복 키)가 있거나 필수 열에 대한 데이터를 제공하지 않을 때마다 Doctrine은 엔티티 관리자를 닫습니다. 여전히 데이터베이스와 상호 작용하려면 JGrinon에서resetManager()
언급 한 메서드를 호출하여 Entity Manger를 재설정해야합니다 .
내 응용 프로그램에서 나는 모두 같은 일을하고있는 여러 RabbitMQ 소비자를 실행하고있었습니다. 엔티티가 데이터베이스에 있는지 확인하고 있다면 반환하고 생성하지 않으면 반환 한 다음 반환합니다. 해당 엔티티가 이미 존재하는지 확인하고 생성하는 사이 몇 밀리 초 동안 다른 소비자가 동일한 작업을 수행하고 누락 된 엔티티를 생성하여 다른 소비자에게 중복 키 예외 ( 경쟁 조건 )를 발생시킵니다.
이로 인해 소프트웨어 설계 문제가 발생했습니다. 기본적으로 내가하려는 것은 하나의 트랜잭션에서 모든 엔티티를 만드는 것입니다. 이것은 대부분의 경우 자연 스럽지만 제 경우에는 확실히 개념적으로 잘못되었습니다. 다음 문제를 고려하십시오. 이러한 종속성이있는 football Match 엔티티를 저장해야했습니다.
- 그룹 (예 : 그룹 A, 그룹 B ...)
- 라운드 (예 : 준결승전 ...)
- 장소 (예 : 경기가 열리는 경기장)
- 경기 상태 (예 : 전반전, 풀 타임)
- 경기를하는 두 팀
- 경기 자체
이제 장소 생성이 경기와 동일한 트랜잭션에 있어야하는 이유는 무엇입니까? 데이터베이스에없는 새 장소를 방금 받았을 수 있으므로 먼저 만들어야합니다. 그러나 해당 장소에서 다른 경기를 주최 할 수 있으므로 다른 소비자도 동시에 제작을 시도 할 수 있습니다. 그래서 내가해야 할 일은 중복 키 예외에서 엔티티 관리자를 재설정하고 있는지 확인하는 별도의 트랜잭션에서 먼저 모든 종속성을 만드는 것입니다. 일치 항목 옆에있는 모든 엔티티는 잠재적으로 다른 소비자의 다른 트랜잭션의 일부가 될 수 있기 때문에 "공유"로 정의 될 수 있습니다. "공유"되지 않는 것은 동시에 두 소비자가 만들지 않을 일치 자체가 있습니다.
이 모든 것이 또 다른 문제로 이어졌습니다. 엔티티 관리자를 재설정하면 재설정하기 전에 검색 한 모든 객체는 완전히 새로운 Doctrine 용입니다. 그래서 교리는 실행하려고하지 않습니다 UPDATE를 그들 그러나에 INSERT ! 따라서 논리적으로 올바른 트랜잭션에서 모든 종속성을 만든 다음 대상 엔터티로 설정하기 전에 데이터베이스에서 모든 개체를 다시 검색해야합니다. 다음 코드를 예로 고려하십시오.
$group = $this->createGroupIfDoesNotExist($groupData);
$match->setGroup($group);
$venue = $this->createVenueIfDoesNotExist($venueData);
$round = $this->createRoundIfDoesNotExist($roundData);
그래서 이것이 내가해야한다고 생각하는 방법입니다.
$group = $this->createGroupIfDoesNotExist($groupData);
$venue = $this->createVenueIfDoesNotExist($venueData);
$round = $this->createRoundIfDoesNotExist($roundData);
$group = $this->getGroup($groupData);
$venue = $this->getVenue($venueData);
$round = $this->getGroup($roundData);
$match->setGroup($group);
$match->setVenue($venue);
$match->setRound($round);
$matchTeamHome = new MatchTeam();
$matchTeamHome->setMatch($match);
$matchTeamHome->setTeam($teamHome);
$matchTeamAway = new MatchTeam();
$matchTeamAway->setMatch($match);
$matchTeamAway->setTeam($teamAway);
$match->addMatchTeam($matchTeamHome);
$match->addMatchTeam($matchTeamAway);
$em->persist($match);
$em->persist($matchTeamHome);
$em->persist($matchTeamAway);
$em->flush();
나는 그것이 도움이되기를 바랍니다 :)