当前位置: 首页 > 知识库问答 >
问题:

Symfony2多个关系还保存现有的相关实体

惠诚
2023-03-14

我在Symfony2.8上遇到了一个多实体关系的问题。我有实体旅行,它可以由许多经验实体组成。

以下是我的旅行定义:

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;
    }
}

在控制器中,用户可以生成一个新的行程,将对象置于会话中以调用它,直到真正的关联。

/**
 * @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\u trip条目,一切正常。在第二次调用时,具有不同经验的trip persisting正在寻找经验实体上的级联,抛出错误:

通过关系“MyBundle\entity\Trip#experiences”找到了一个新实体,该关系未配置为级联实体的持久化操作:。要解决此问题,请对此未知实体显式调用EntityManager#persist(),或在映射中配置cascade persist此关联,例如@manytone(..,cascade={“persist”})。

这是因为试图添加一个新的体验实体,事实上,由于字段的唯一性,使用级联{“persist”}在体验复制上生成一个sql异常。

Sonata TripAdmin类可以正确管理相同的模型,而无需尝试在旅行持续时添加新的体验,而无需避免创建体验旅行实体。在experience_trip表中,我可以正确地看到正确的关联。

为什么要保存行程,第二次尝试插入新的体验?

提前谢谢,对不起我的英语。

共有1个答案

姚凯歌
2023-03-14

我自己找到了解决方案,也感谢这条评论。

由于某种原因,会话中的实体已分离,并且不是有效的实体。所以,坚持尝试再次添加它。

 类似资料:
  • 我有2个实体(我删除了无用的字段): 而且 这似乎符合我的情况(也是我当前的实现),但它不起作用。 我得到以下错误消息: 来自MySQL: 临时解决方案是从存储库中检索所有相应的权限(按permissionName搜索)。那么保存效果很好。逻辑上是正确的,但我希望有一个更简单的程序...

  • 问题内容: 我想了解Doctrine和Symfony2的多对多关系是如何工作的。 我已经重新创建了官方文档(goo.gl/GYcVE0)中显示的示例,并且我有两个实体类: 用户 和 组 ,如下所示。 如果我更新数据库,则会得到以下MySQL模式: 问题在于,在Symfony2中,我需要 实体 来生成查询,在这种情况下,我没有与表相关联的实体,因为该表是由框架自动创建的。 那么,如何检索与此关系表有

  • 我正在学习SpringJPA,我从将对象映射到表开始。我对OneToOne和OneToMany的关系没有问题,但我不太明白为什么我不能预先列出一个与许多关系相关的对象。我有一本可以有很多作者的书,还有一本可以有很多书的作者。通过中间表book_author正确生成模式(我可以在MySql Workbench中看到),但我得到以下示例: Hibernate:在作者(名字、姓氏)中插入值(?,) Hi

  • 问题内容: 我要删除具有多对多关系的一个站点上的表中的一行。我还想删除该关系另一侧的所有相关行。 例如,假设我有以下表格,并且想从中删除一行。我也想从中删除所有相关的行,当然,也删除其中不再需要的任何行。 我知道如何在查询中连接以上表格。但是我看不到如何删除整个关系中的数据。 注意:关系的两端都实现级联删除。因此,例如,从中删除行将删除中的任何相关行。但是显然,这不会传播到表中。 问题答案: 我认

  • 我创建了一个自定义的推送()方法,它以级联的方式保存所有模型的关系,并收集实体和子实体详细信息的完整快照用于审计日志。 一切都与belongsTo配合良好,并且有很多关系。我只是这样做: 但问题在于他只有一种关系。它不提供任何方法将相关模型附加到我的根模型而不首先保存它。HasOne关系在Laravel中只有save()方法: 如您所见,它不仅关联,而且保存了模型。为了能够检测字段的所有更改,我的

  • 我有一个实体: 要创建上述实体并将其保存到JPA存储库中,我将执行以下操作: 由于DB中的表存储了候选对象的FK,我认为设置一个id就足够了。但JPA希望我设置候选对象。这迫使我查询候选存储库。 是否需要从候选库中查询候选人以保存,或者如果我有可用的候选人id,我不能直接设置它?