Symfony协会将OneToOne和OneToMany映射到同一实体 [英] Symfony Association Mapping OneToOne and OneToMany to Same Entity

查看:527
本文介绍了Symfony协会将OneToOne和OneToMany映射到同一实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表示主页面记录的 View 实体,然后我有一个关联的实体,名为 ViewVersion 它随着时间的推移存储实体的多个版本。 View 实体在 VersionId ViewVersion c>字段。这使得一个简单的OneToOne关联。但是在某些情况下,我也希望得到与 View 实体相关联的所有版本。如果我想允许用户查看旧版本并恢复。所以我将需要另一个映射,这是OneToMany。第一个 viewVersion 将映射到活动的已发布版本,第二个 viewVersions 将显示所有版本。 / p>

实体定义

  / ** 
* @ ORM\Entity
* @ ORM\Table(name =view)
* @ ORM\Entity(repositoryClass =Gutensite\CmsBundle\Entity\ View \ViewRepository)
* /
class View extends Entity\Base {

/ **
* @ ORM\OneToOne(targetEntity =\\ \\ Gutensite\CmsBundle\Entity\View \ViewVersion,inversedBy =view,cascade = {persist,remove},orphanRemoval = true)
* @ ORM\JoinColumn(name =versionId,referencedColumnName =id)
* /
protected $ viewVersion;

/ **
* @ ORM\Column(type =integer,nullable = true)
* /
protected $ versionId = NULL;

/ **
* @ ORM\OneToMany(targetEntity =\Gutensite\CmsBundle\Entity\View\ViewVersion,mappedBy =viewAll,cascade = {persist,remove},orphanRemoval = true)
* /
protected $ viewVersions;
}

/ **
* @ ORM\Entity
* @ ORM\Table(name =view_version)
* @ORM \Entity(repositoryClass =Gutensite\CmsBundle\Entity\View\ViewVersionRepository)
* /
class ViewVersion extends Entity\Base {

/ * *
* @ ORM\OneToOne(targetEntity =\Gutensite\CmsBundle\Entity\View\View,mappedBy =viewVersion,cascade = {persist})
* /
protected $ view;

/ **
* @ ORM\ManyToOne(targetEntity =\Gutensite\CmsBundle\Entity\View\View,inversedBy =viewVersions)
* @ ORM\JoinColumn(name =viewId,referencedColumnName =id)
* /
protected $ viewAll;

/ **
*此版本所属的主视图实体。
* @ ORM\Column(type =integer,nullable = true)
* /
protected $ viewId;

}

这个工作,但建议有两个关联与这样一样的实体?还是这是一个很糟糕的主意?



ViewVersion 实体将引用单个查看实体在这两种情况下,映射关联需要两个单独的变量,例如查看 ViewAll 。我不完全确定内部协会是如何工作的,以及如何使用映射的参考变量。



或者,我可以摆脱OneToOne关联,并且只需设置一个ViewRepository函数来获取基于versionId的当前发布版本(就像用于与getVersion()一样的旧映射实体)。这将会起作用,但是它是否内部开销较大,因为它会产生两个查询,否则Doctrine会很聪明,可以优化这一点,就像使用getVersion()一样。



注意:
这些其他 答案不完整。



参考资料:
http://docs.doctrine-project.org/projects/doctrine-orm /en/latest/reference/working-with-associations.html
http://doctrine-orm.readth edocs.org/en/2.0.x/reference/association-mapping.html#one-to-many-bidirectional

解决方案

根据@jmather的建议我决定这个模型是好的,因为我需要一个View实体,其他实体可以访问(例如路由指向单个视图的网址,即页面)。



我已将View的OneToOne关系改为单向,因为ViewVersion已经通过其他OneToMany与View关联需要两条路径)。



这允许我为$ view-> getPublished()方便地使用一个简单的方法,似乎更合乎逻辑。

  / ** 
* @ ORM\Entity
* @ ORM\Table(name =view)
* /
类查看扩展Entity\Base {

/ **
*这是一个OneToOne单向关联,这样我们可以得到
*当前发布的版本很容易,基于publishedId。
* @ ORM\OneToOne(targetEntity =\Gutensite\CmsBundle\Entity\View\TestVersion)
* @ ORM\JoinColumn(name =publishedId,referencedColumnName = id)
* /
protected $ published;

/ **
* @ ORM\Column(type =integer,nullable = true)
* /
protected $ publishedId = NULL;

/ **
*这是所有版本的常规OneToMany双向协会。
* @ ORM\OneToMany(targetEntity =\Gutensite\CmsBundle\Entity\View\ViewVersion,mappedBy =view,cascade = {persist,remove},orphanRemoval = true)
* /
protected $ versions;
}

/ **
* @ ORM\Entity
* @ ORM\Table(name =view_version)
* /
class ViewVersion extends Entity\Base {


/ **
* @ ORM\ManyToOne(targetEntity =\Gutensite\CmsBundle\Entity\\ \\ view \View,inversedBy =versions)
* @ ORM\JoinColumn(name =viewId,referencedColumnName =id)
* /
protected $ view;

/ **
*此版本所属的主视图实体。
* @ ORM\Column(type =integer,nullable = true)
* /
protected $ viewId;

}

但是,我发现只要$ view-> publishedId设置为视图无法从数据库中删除,因为外键约束(即使它是单向的)。所以我必须打破这个外键链接,然后再删除。我觉得没事。我在此发布了有关此处的详细信息:导致数据库的重叠实体关联删除实体时的外键限制错误


I have a View entity that represents the primary page record, and then I have an associated entity called ViewVersion which stores multiple versions of the entity as it's changed over time. The View entity sets the current "Published" ViewVersion in the VersionId field. This makes for a simple OneToOne association. But in some contexts I will also want to get all the versions associated with this View entity, e.g. if I want to allow the user to review older versions and revert back. So I will need another mapping which is a OneToMany. The first viewVersion will map to the active "published" version, and the second viewVersions will show all the versions.

Entity Definitions

/**
* @ORM\Entity
* @ORM\Table(name="view")
* @ORM\Entity(repositoryClass="Gutensite\CmsBundle\Entity\View\ViewRepository")
*/
class View extends Entity\Base {

    /**
    * @ORM\OneToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\ViewVersion", inversedBy="view", cascade={"persist", "remove"}, orphanRemoval=true)
    * @ORM\JoinColumn(name="versionId", referencedColumnName="id")
    */
    protected $viewVersion;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $versionId = NULL;

    /**
 * @ORM\OneToMany(targetEntity="\Gutensite\CmsBundle\Entity\View\ViewVersion", mappedBy="viewAll", cascade={"persist", "remove"}, orphanRemoval=true)
 */
protected $viewVersions;
}

/**
* @ORM\Entity
* @ORM\Table(name="view_version")
* @ORM\Entity(repositoryClass="Gutensite\CmsBundle\Entity\View\ViewVersionRepository")
*/
class ViewVersion extends Entity\Base {

    /**
    * @ORM\OneToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\View", mappedBy="viewVersion", cascade={"persist"})
    */
    protected $view;

    /**
    * @ORM\ManyToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\View", inversedBy="viewVersions")
    * @ORM\JoinColumn(name="viewId", referencedColumnName="id")
    */
    protected $viewAll;

    /**
    * The primary view entity that this version belongs to.
    * @ORM\Column(type="integer", nullable=true)
    */
    protected $viewId;

}

This "works" but is it recommended to have two associations with the same entity like this? Or is this a really bad idea?

The ViewVersion entity will reference a single View entity in both cases, but the mapped associations need two separate variables, e.g. View and ViewAll. I'm not exactly sure how the internals work for the association, and how the reference variable with the mapping is used.

Alternatively, I could get rid of the OneToOne association, and just set a ViewRepository function to get the current published version based on the versionId (just like the old mapped entity used to do with the getVersion()). That would work, but is it more internal overhead, because it would make two queries... or will Doctrine be smart enough to optimize this, just like it did with the getVersion().

NOTE: These other answers are not complete.

References: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html http://doctrine-orm.readthedocs.org/en/2.0.x/reference/association-mapping.html#one-to-many-bidirectional

解决方案

Per the advice from @jmather I've decided this model is "okay", because I need a single View entity that other entities can access (e.g. Routing urls that point to a single View, i.e. "page").

I've changed the OneToOne relationship for View to be unidirectional only, because the ViewVersion already has an association back to the View via the other OneToMany (so it doesn't need two paths back).

This allows me to keep a simple method for $view->getPublished() handy and seems more logical.

/**
* @ORM\Entity
* @ORM\Table(name="view")
*/
class View extends Entity\Base {

    /**
    * This is a OneToOne Unidirectional association, just so that we can get the
    * current published version easily, based on the publishedId.
    * @ORM\OneToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\TestVersion")
    * @ORM\JoinColumn(name="publishedId", referencedColumnName="id")
    */
    protected $published;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $publishedId = NULL;

    /**
     * This is the regular OneToMany Bi-Directional Association, for all the versions.
 * @ORM\OneToMany(targetEntity="\Gutensite\CmsBundle\Entity\View\ViewVersion", mappedBy="view", cascade={"persist", "remove"}, orphanRemoval=true)
 */
protected $versions;
}

/**
* @ORM\Entity
* @ORM\Table(name="view_version")
*/
class ViewVersion extends Entity\Base {


    /**
    * @ORM\ManyToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\View", inversedBy="versions")
    * @ORM\JoinColumn(name="viewId", referencedColumnName="id")
    */
    protected $view;

    /**
    * The primary view entity that this version belongs to.
    * @ORM\Column(type="integer", nullable=true)
    */
    protected $viewId;

}

However, I've discovered that as long as the $view->publishedId is set the view can't be deleted from the database because of foreign key constraints (even though it's uni-directional). So I have to break that foreign key link before removing. I think that's fine. I posted details about that here: Overlapping Entity Association causing Database Foreign Key Constraint Errors when Removing Entity

这篇关于Symfony协会将OneToOne和OneToMany映射到同一实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆