11

我目前的模型结构如下:

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="related_type", type="string")
 * @ORM\DiscriminatorMap({"type_one"="TypeOne", "type_two"="TypeTwo"})
 */
abstract class BaseEntity {

    ... (all the usual stuff, IDs, etc)

    /**
     * @ORM\OneToMany(targetEntity="Comment", mappedBy="baseEntity")
     */
    private $comments;
}

/**
 * @ORM\Entity
 */
class TypeOne extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;
}

/**
 * @ORM\Entity
 */
class TypeTwo extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;   
}

/**
 * @ORM\Entity
 */
class Comment {

    ... (all the usual stuff, IDs, etc)

    /**
     * @ORM\ManyToOne(targetEntity="BaseEntity", inversedBy="comments")
     */
    private $baseEntity;
}

这里的想法是能够将评论绑定到任何其他表。到目前为止,这一切似乎都运行良好(当然,我仍在探索设计选项,因此可能有更好的方法来做到这一点......),但我注意到的一件事是子类有一些共同的领域我想搬到一个共同的父类。我不想将它们移到 BaseEntity 中,因为会有其他对象是 BaseEntity 的子对象,但不会有这些字段。

我考虑过在中间创建一个 MappedSuperclass 父类,如下所示:

/**
 * @ORM\MappedSuperclass
 */
abstract class Common extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;       
}

/**
 * @ORM\Entity
 */
class TypeOne extends Common {}

/**
 * @ORM\Entity
 */
class TypeTwo extends Common {}

我认为这会起作用,但是教义数据库模式生成器抱怨我不能在 MappedSuperclass 上进行 OneToMany 映射。我没想到这会成为问题,因为 OneToMany 映射仍在根 BaseEntity 和 Comment 表之间。我应该使用不同的结构,还是以其他方式使这些字段通用而不将它们添加到 BaseEntity 上?

4

1 回答 1

14

从文档:

映射的超类是一个抽象或具体的类,它为其子类提供持久的实体状态和映射信息, 但它本身并不是一个实体。通常,这种映射超类的目的是定义多个实体类共有的状态和映射信息。

也就是说,您如何将一个实体与一个不存在的实体联系起来?

更多来自文档:

映射的超类不能是实体,它不是可查询的,并且由映射的超类定义的持久关系必须是单向的(仅具有拥有方)。这意味着在映射的超类上根本不可能进行一对多关联。 此外,只有当映射的超类目前仅在一个实体中使用时,多对多关联才是可能的。为了进一步支持继承,必须使用单表或联表继承特性。

来源:http ://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html


更新

因为您的 MappedSuperClass 扩展了 BaseEntity,它也继承了 BaseEntity 的关联,就好像它是它自己的一样。所以你实际上在 MappedSuperClass 上有一个 OneToMany。

为了解决这个问题,你需要修改/扩展原则以按照你想要的方式工作。

就本机功能而言,您有两种选择:

类表继承 您的公共类和生成的 DB 表示将具有公共字段,而子类现在将仅具有特定于它们自己的字段。不幸的是,如果您只是为了对公共字段进行分组而尝试对它们进行分组,那么这可能是对您的数据的错误陈述。

使公共实体成为一个实体 看起来所有映射的超类都是一个不在数据库中表示的实体。因此,改为使 common 成为一个实体。缺点是你最终会得到一个数据库表,但你可以删除它。

我建议您再次查看您的数据,并确保您只对名称和用途都相同的字段进行分组。例如,ComputerBox、ShoeBox、Man 和 Woman 可能都具有“height”属性,但在这种情况下,我不建议使用具有“height”属性的 Common 类来继承它们。相反,我将有一个 Box,其中包含 ComputerBox 和 ShoeBox 共有的字段,而我将有一个 Person,其中包含 Man 和 Woman 共有的字段。在这种情况下,如果您愿意,类表继承或单表将完美运行。

如果您的数据遵循该示例,请使用单表或类表继​​承。如果没有,我可能会建议不要对字段进行分组。

于 2012-09-05T18:38:25.077 回答