【问题标题】:Many to Many, One to Many or Many to One多对多、一对多或多对一
【发布时间】:2014-10-25 18:34:15
【问题描述】:

我试图了解 Doctrine 2 ORM 关系,我以为我已经掌握了窍门,但在阅读了一些 symfony 食谱条目后,我怀疑我实际上有点困惑。

我目前有一个系统,其中一个模板可以包含多个模块(每种类型包括多个模块),并且多个模板可以使用同一个模块。

我认为这将保证多对多关系,并且确实看着我的桌子,它似乎工作得很好。

但是,当我编写数据库查询时,我意识到我需要以特定顺序加载模块,这意味着我的连接表需要有第三个“order_by”列。我读过一个真正的连接表只有两列。

因此混乱。我应该在我的实体中进行什么设置?

【问题讨论】:

    标签: symfony orm doctrine-orm entities


    【解决方案1】:

    就像@Kris 所说的那样——你会选择一对多的中间实体。如果您选择多对多,那么您将没有中间表的类文件,这在大多数情况下是一个问题。

    M-N 假设: 一个学生学习多门课程,一门课程可以有许多学生。

    以下两个示例都在数据库中为您提供了此 ERD,但您希望选择 ONE to MANY 版本。

    多对多:

    这将在数据库中创建 StudentCourse 实体,但您看不到实际的类文件供您处理。

    class Student
    {
        protected $id;
        protected $name;
    
        /**
         * @ORM\ManyToMany(targetEntity="Course")
         * @ORM\JoinTable(
         * name="StudentCourse",
         * joinColumns={@ORM\JoinColumn(name="studentId", referencedColumnName="id")},
         * inverseJoinColumns={@ORM\JoinColumn(name="courseId", referencedColumnName="id")}
         * )
         */
        private $course;
    }
    
    class Course
    {
        protected $id;
        protected $name;
    }
    

    一对多:

    这将在数据库中创建StudentCourse 实体,如您所见,在编码时有一个实际的类文件供您处理,例如persist() 等。

    class Student
    {
        protected $id;
        protected $name;
    
        /**
         * @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="studentMap",
         * cascade={"persist", "remove"})
         */
        protected $studentInverse;
    }
    
    class StudentCourse
    {
        protected $id;
    
        /**
         * @ORM\ManyToOne(targetEntity="Course", inversedBy="courseInverse")
         * @ORM\JoinColumn(name="course", referencedColumnName="id",
         * nullable=false, onDelete="CASCADE")
         */
        protected $courseMap;
    
        /**
         * @ORM\ManyToOne(targetEntity="Student", inversedBy="studentInverse")
         * @ORM\JoinColumn(name="student", referencedColumnName="id",
         * nullable=false, onDelete="CASCADE")
         */
        protected $studentMap;
    }
    
    class Course
    {
        protected $id;
        protected $name;
    
        /**
         * @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="courseMap",
         * cascade={"persist", "remove"})
         */
        protected $courseInverse;
    }
    

    编辑: onDelete="CASCADE"cascade={"persist", "remove"} 位不是强制性的。他们处理数据冗余。 Is it bad to use redundant relationships?

    【讨论】:

    • 哇谢谢你解释得这么清楚!这非常有帮助。
    • 没问题。您可能已经知道,但我只是在 EDIT 下添加了一条注释。
    • 好的,我已经进行了这些更改,并且数据库本身似乎设置正确。然而,我的装置似乎不再快乐了。当我尝试加载它们时,我收到了我添加到问题底部的错误。
    • 您介意打开一个新问题并在此处发布链接,因为这是一个新问题。我有解决方案,但无法发表评论。
    【解决方案2】:

    你需要一个 OneToMany/ManyToOne 如果您不需要保存订单,那将是多对多,但既然您这样做了,那么不幸的是,该中间表现在必须是它自己的实体。 所以你需要以下实体

    模板

    使用 OneToMany 到

    TemplateModules(这个名字可能更好)

    使用多对一来

    模块

    【讨论】:

    • 这是有道理的。非常感谢。
    猜你喜欢
    • 2017-05-15
    • 2021-04-01
    • 1970-01-01
    • 2019-09-15
    • 2023-04-06
    • 1970-01-01
    • 2011-03-08
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多