4

我已经阅读了Doctrine 2 Inheritance Mapping with Association,但如果你需要Animal自己成为一个实体,比如创建选项列表。

在这种情况下,a 的鉴别器列Pet位于 的物种列中animal table

宠物数据库架构

所以课程会是这样的。

class Animal
{
    $id;
    $species;
}

/**
 * @Table(name="animal")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="species", type="string")
 * @DiscriminatorMap({"dog" = "Dog", "cat" = "Cat"})
 */
abstract class Pet
{
    $id
    $species;
}

class Dog extends Pet { }

class Cat extends Pet { }

class Owner 
{
    /**
     * @OneToMany(targetEntity="Pet")
     */
    $pets
}

我看到了几个问题。

  1. animal表没有外键owner。所以这个 $pets协会是行不通的。

  2. Animal并且Pet或多或少是同一件事。如果有人更改了Animal这些更改中的某些内容,则不会反映在任何子Pet类中。

第一个问题的可能解决方案是有一个名为 的额外表pet,但关联仍然存在问题,因为鉴别器列仍在animal表中并且复制列pet会破坏规范化。

在此处输入图像描述

4

1 回答 1

3

我不确定是否完全理解您的问题,但我会尝试一下:

  • APet是一个,在你的类层次结构中明确表示Animal它是有意义的。请注意,抽象类可以子类化具体类。这样,您仍然可以实例化 a 、 a或 a ,但不能实例化 a ;PetAnimalAnimalDogCatPet
  • Animal类可以有自己的鉴别器值,这使得它可以用 Doctrine 持久化。然后,您可以创建并持久化 aDog或 a Cat,甚至是泛型Animal;
  • Animal需要对其所有者的引用
  • Owner现在与 有一对多的关系Animal
  • species列是一个鉴别器,不会为您的域模型增加任何价值(类名会告诉您Animal您正在处理哪个),因此我建议删除此属性。

最后一点,你真的需要Pet上课吗?如果 Pet 没有特定于 an Animal(即类为空),那么您可能应该将其从类层次结构中删除。

class Owner {
    /**
     * @OneToMany(targetEntity="Animal")
     */
    protected $animals;
}

/**
 * @Table(name="animal")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="species", type="string")
 * @DiscriminatorMap({"animal" = "Animal", "dog" = "Dog", "cat" = "Cat"})
 */
class Animal {
    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id;

    /** @ManyToOne(targetEntity="Owner") */
    protected $owner;
}

abstract class Pet extends Animal {
    // Do you really need this class?
}

class Dog extends Pet {
    // ...
}

class Cat extends Pet {
    // ...
}

关于您的数据库结构,我建议进行以下更改:

  • owner_idDog&移到桌子上CatAnimal
  • animal_idDog&Cat表中删除;他们将与表共享id价值(一对一)。Animal
于 2011-11-27T23:44:46.693 回答