多对多、一对多或多对一
Posted
技术标签:
【中文标题】多对多、一对多或多对一【英文标题】:Many to Many, One to Many or Many to One 【发布时间】:2014-10-25 18:34:15 【问题描述】:我试图了解 Doctrine 2 ORM 关系,我以为我已经掌握了窍门,但在阅读了一些 symfony 食谱条目后,我怀疑我实际上有点困惑。
我目前有一个系统,其中一个模板可以包含多个模块(每种类型包括多个模块),并且多个模板可以使用同一个模块。
我认为这将保证多对多关系,并且确实看着我的桌子,它似乎工作得很好。
但是,当我编写数据库查询时,我意识到我需要以特定顺序加载模块,这意味着我的连接表需要有第三个“order_by”列。我读过一个真正的连接表只有两列。
因此混乱。我应该在我的实体中进行什么设置?
【问题讨论】:
【参考方案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 下添加了一条注释。 好的,我已经进行了这些更改,并且数据库本身似乎设置正确。然而,我的装置似乎不再快乐了。当我尝试加载它们时,我收到了我添加到问题底部的错误。 您介意打开一个新问题并在此处发布链接,因为这是一个新问题。我有解决方案,但无法发表评论。 在这里:***.com/questions/26575174/… :)【参考方案2】:你需要一个 OneToMany/ManyToOne 如果您不需要保存订单,那将是多对多,但既然您这样做了,那么不幸的是,该中间表现在必须是它自己的实体。 所以你需要以下实体
模板
使用 OneToMany 到
TemplateModules(这个名字可能更好)
使用多对一来
模块
【讨论】:
这是有道理的。非常感谢。以上是关于多对多、一对多或多对一的主要内容,如果未能解决你的问题,请参考以下文章