Symfony2 ManyToMany 关系也保存存在的相关实体
Symfony2 ManyToMany relation save also the existent related entity
我在 Symfony2.8 上遇到了 Doctrine ManyToMany 实体关系的问题。
我有实体 Trip,它可以由许多 Experience 实体组成。
这是我的旅行定义:
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Trip
*
* @ORM\Table(name="trip")
* @ORM\Entity(repositoryClass="MyBundle\Repository\TripRepository")
* @ORM\HasLifecycleCallbacks
*/
class Trip
{
use ORMBehaviors\Timestampable\Timestampable;
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// other fields
/**
* @ORM\ManyToMany(targetEntity="MyBundle\Entity\Experience", inversedBy="trips")
* @ORM\JoinTable(name="experience_trip",
* joinColumns={
* @ORM\JoinColumn(name="trip_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="experience_id", referencedColumnName="id")
* }
* )
*/
private $experiences;
/**
* Constructor
*/
public function __construct()
{
$this->experiences = new \Doctrine\Common\Collections\ArrayCollection();
}
// other setters and getters
/**
* Add experience
*
* @param \MyBundle\Entity\Experience $experience
*
* @return Trip
*/
public function addExperience(\MyBundle\Entity\Experience $experience)
{
$this->experiences[] = $experience;
return $this;
}
/**
* Remove experience
*
* @param \MyBundle\Entity\Experience $experience
*/
public function removeExperience(\MyBundle\Entity\Experience $experience)
{
$this->experiences->removeElement($experience);
}
/**
* Get experiences
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getExperiences()
{
return $this->experiences;
}
}
在另一边我有体验实体:
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Experience
*
* @ORM\Table(name="experience")
* @ORM\Entity(repositoryClass="MyBundle\Repository\ExperienceRepository")
*/
class Experience
{
use ORMBehaviors\Translatable\Translatable;
use ORMBehaviors\Timestampable\Timestampable;
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="MyBundle\Entity\Trip", mappedBy="experiences")
*/
private $trips;
// other fields
/**
* Constructor
*/
public function __construct()
{
$this->trips = new \Doctrine\Common\Collections\ArrayCollection();
}
// other setters and getters
/**
* Add trip
*
* @param \MyBundle\Entity\Trip $trip
*
* @return Experience
*/
public function addTrip(\MyBundle\Entity\Trip $trip)
{
$this->trips[] = $trip;
return $this;
}
/**
* Remove trip
*
* @param \MyBundle\Entity\Trip $trip
*/
public function removeTrip(\MyBundle\Entity\Trip $trip)
{
$this->trips->removeElement($trip);
}
/**
* Get trips
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getTrips()
{
return $this->trips;
}
}
在controller中,用户可以生成一个新的Trip,将对象放到session中调用,直到真正关联起来。
/**
* @Route("/add-experience", name="add_experience")
*/
public function addExperienceAction(Request $request)
{
$experienceId = $request->query->get('experience');
$em = $this->getDoctrine()->getManager();
$experience = $em->getRepository('MyBundle:Experience')->find($experienceId);
if (!$experience || !get_class($experience) == 'MyBundle:Experience') {
$response = array("message" => "Experience not found", "success" => false);
return new Response(json_encode($response));
}
$session = $request->getSession();
$trip = $session->get('trip');
// This service only construct parameters
$searchParameters = $this->get('mybundle.search')->buildSearchParameters();
if (!$trip) {
$trip = new Trip();
$trip->setStartDate($searchParameters['startDate']);
$trip->setEndDate($searchParameters['endDate']);
}
$trip->addExperience($experience);
$trip->setClient($this->getUser()); /** user can be null */
$em->persist($trip);
$em->flush();
$session->set('trip', $trip);
$response = array("message" => "Experience n.$experienceId added correctly", "success" => true);
return new Response(json_encode($response));
}
问题。
第一次调用时,它就像一个魅力,添加 experience_trip 条目,一切正常。
在第二次调用时,具有不同的经验,坚持旅行正在寻找经验实体的级联,抛出错误:
A new entity was found through the relationship 'MyBundle\Entity\Trip#experiences' that was not configured to cascade persist operations for entity: . To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).
这是因为尝试添加一个新的体验实体,事实上,使用 cascade={"persist"}
,由于字段的唯一性,在体验重复时生成 sql 异常。
同一模型由 Sonata TripAdmin class 正确管理,而不是尝试在旅行持续中添加新体验,而不是避免创建 ExperienceTrip 实体。在 experience_trip table 中我可以正确地看到正确的关联。
为什么保存行程,第二次尝试插入新体验?
提前致谢,对不起我的英语。
我自己找到了解决方案,也感谢。
由于某种原因,会话中的实体已分离并且不是有效实体。所以坚持再尝试添加。
我在 Symfony2.8 上遇到了 Doctrine ManyToMany 实体关系的问题。 我有实体 Trip,它可以由许多 Experience 实体组成。
这是我的旅行定义:
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Trip
*
* @ORM\Table(name="trip")
* @ORM\Entity(repositoryClass="MyBundle\Repository\TripRepository")
* @ORM\HasLifecycleCallbacks
*/
class Trip
{
use ORMBehaviors\Timestampable\Timestampable;
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// other fields
/**
* @ORM\ManyToMany(targetEntity="MyBundle\Entity\Experience", inversedBy="trips")
* @ORM\JoinTable(name="experience_trip",
* joinColumns={
* @ORM\JoinColumn(name="trip_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="experience_id", referencedColumnName="id")
* }
* )
*/
private $experiences;
/**
* Constructor
*/
public function __construct()
{
$this->experiences = new \Doctrine\Common\Collections\ArrayCollection();
}
// other setters and getters
/**
* Add experience
*
* @param \MyBundle\Entity\Experience $experience
*
* @return Trip
*/
public function addExperience(\MyBundle\Entity\Experience $experience)
{
$this->experiences[] = $experience;
return $this;
}
/**
* Remove experience
*
* @param \MyBundle\Entity\Experience $experience
*/
public function removeExperience(\MyBundle\Entity\Experience $experience)
{
$this->experiences->removeElement($experience);
}
/**
* Get experiences
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getExperiences()
{
return $this->experiences;
}
}
在另一边我有体验实体:
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Experience
*
* @ORM\Table(name="experience")
* @ORM\Entity(repositoryClass="MyBundle\Repository\ExperienceRepository")
*/
class Experience
{
use ORMBehaviors\Translatable\Translatable;
use ORMBehaviors\Timestampable\Timestampable;
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="MyBundle\Entity\Trip", mappedBy="experiences")
*/
private $trips;
// other fields
/**
* Constructor
*/
public function __construct()
{
$this->trips = new \Doctrine\Common\Collections\ArrayCollection();
}
// other setters and getters
/**
* Add trip
*
* @param \MyBundle\Entity\Trip $trip
*
* @return Experience
*/
public function addTrip(\MyBundle\Entity\Trip $trip)
{
$this->trips[] = $trip;
return $this;
}
/**
* Remove trip
*
* @param \MyBundle\Entity\Trip $trip
*/
public function removeTrip(\MyBundle\Entity\Trip $trip)
{
$this->trips->removeElement($trip);
}
/**
* Get trips
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getTrips()
{
return $this->trips;
}
}
在controller中,用户可以生成一个新的Trip,将对象放到session中调用,直到真正关联起来。
/**
* @Route("/add-experience", name="add_experience")
*/
public function addExperienceAction(Request $request)
{
$experienceId = $request->query->get('experience');
$em = $this->getDoctrine()->getManager();
$experience = $em->getRepository('MyBundle:Experience')->find($experienceId);
if (!$experience || !get_class($experience) == 'MyBundle:Experience') {
$response = array("message" => "Experience not found", "success" => false);
return new Response(json_encode($response));
}
$session = $request->getSession();
$trip = $session->get('trip');
// This service only construct parameters
$searchParameters = $this->get('mybundle.search')->buildSearchParameters();
if (!$trip) {
$trip = new Trip();
$trip->setStartDate($searchParameters['startDate']);
$trip->setEndDate($searchParameters['endDate']);
}
$trip->addExperience($experience);
$trip->setClient($this->getUser()); /** user can be null */
$em->persist($trip);
$em->flush();
$session->set('trip', $trip);
$response = array("message" => "Experience n.$experienceId added correctly", "success" => true);
return new Response(json_encode($response));
}
问题。 第一次调用时,它就像一个魅力,添加 experience_trip 条目,一切正常。 在第二次调用时,具有不同的经验,坚持旅行正在寻找经验实体的级联,抛出错误:
A new entity was found through the relationship 'MyBundle\Entity\Trip#experiences' that was not configured to cascade persist operations for entity: . To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).
这是因为尝试添加一个新的体验实体,事实上,使用 cascade={"persist"}
,由于字段的唯一性,在体验重复时生成 sql 异常。
同一模型由 Sonata TripAdmin class 正确管理,而不是尝试在旅行持续中添加新体验,而不是避免创建 ExperienceTrip 实体。在 experience_trip table 中我可以正确地看到正确的关联。
为什么保存行程,第二次尝试插入新体验?
提前致谢,对不起我的英语。
我自己找到了解决方案,也感谢
由于某种原因,会话中的实体已分离并且不是有效实体。所以坚持再尝试添加。