如何在Doctrine2中为类表继承指定外键列?
如何指定用于 Doctrine 2 中的类表继承的外键关系的列?例如,采用以下两个类:
/**
* @Entity
* @InhertanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap("person" = "Person", "employee" = "Employee")
*/
class Person
{
/** @Id */
public $id;
/** @Column(type="string") */
public $ssn;
}
/** @Entity */
class Employee
{
/** @Column(type="decimal") */
public $salary;
}
这样,Doctrine 期望的表结构与此类似:
CREATE TABLE `person` (
`id` INT(11) NOT NULL auto_increment,
`ssn` VARCHAR(255) default NULL,
PRIMARY_KEY(`id`)
)
CREATE TABLE `employee` (
`person_id` INT(11) NOT NULL,
`salary` DECIMAL(10,2) default NULL,
PRIMARY_KEY(`person_id`)
)
ALTER TABLE `employee`
ADD CONSTRAINT `person_fk` FOREIGN KEY (`person_id`)
REFERENCES `person` (`id`) ON DELETE CASCADE
有一个指向 person.id
的外键 employee.person_id
。但我如何告诉 Doctrine 使用哪些列呢?我假设 person.id
引用来自 Person
类上的 @Id
注释,但是如果我想创建 FK 以改为 person.ssn
(这是可以想象的,因为 SSN 自然是唯一的)。
如果我有一个旧数据库,其中 employee.person_id
被称为 employee.p_id
该怎么办?
How can I specify the columns that are used for the foreign key relation with Class Table Inheritance in Doctrine 2? For example, take the following two classes:
/**
* @Entity
* @InhertanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap("person" = "Person", "employee" = "Employee")
*/
class Person
{
/** @Id */
public $id;
/** @Column(type="string") */
public $ssn;
}
/** @Entity */
class Employee
{
/** @Column(type="decimal") */
public $salary;
}
With this, Doctrine expects a table structure somewhat along this:
CREATE TABLE `person` (
`id` INT(11) NOT NULL auto_increment,
`ssn` VARCHAR(255) default NULL,
PRIMARY_KEY(`id`)
)
CREATE TABLE `employee` (
`person_id` INT(11) NOT NULL,
`salary` DECIMAL(10,2) default NULL,
PRIMARY_KEY(`person_id`)
)
ALTER TABLE `employee`
ADD CONSTRAINT `person_fk` FOREIGN KEY (`person_id`)
REFERENCES `person` (`id`) ON DELETE CASCADE
There is a foreign key employee.person_id
that points to person.id
. But how can I tell Doctrine which columns to use? I assume that the person.id
reference comes from the @Id
annotation on the Person
class, but what if I want to create the FK to person.ssn
instead (it's conceivable, since SSN are naturally unique).
And what if I have a legacy database where employee.person_id
is called employee.p_id
instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,您在 Employee 类定义中缺少“extends Person”。
据我所知,当您进行这种类型的继承时,学说使用主类中的主键来连接所有其他表,这是预期的行为。
当您进行查询时,学说会将所有子表连接到父表,然后根据鉴别器映射进行水合。考虑到这一点,主键是自动增量 ID 还是唯一字段并不重要。如果您在父类中定义了 ssn,则它将可用于在所有子类中搜索。
这里有一些提示。如果需要,您可以删除自动 id 并使用 ssn 作为主键,然后学说期望您的所有子表都在其中定义相同的字段。为了提高性能,明智的做法是使用整数而不是 255 字符串来进行连接。
如果您想维护自动 id,您可能需要向父类添加唯一索引,这样如果您通过该字段访问类,则不会导致性能下降。
如果您希望类名称为其他名称,而表名称为其他名称,请使用此名称
,但请记住,作为继承一部分的所有表都应使用该名称。
此外,我通常使用 Doctrine 来映射现有数据库并扩展它(迁移到 Doctrine),如果我要添加新功能并且模型需要这样做,我会自己创建映射和表,同时牢记 Doctrine 继承的工作原理。但是,如果您认为可以使用继承对现有表进行建模,那么预计会出现一些麻烦,并且可能需要修改现有表。
希望这有帮助。
First of all, you are missing the "extends Person" in the Employee class definition.
From what I know, when you are doing this type of inheritance, doctrine uses the primary key in the main class to join all other tables, its is expected behavior.
When you do a query, doctrine will join all the child tables to the parent and then hydrate according to the discriminator map. With that in mind, it doesn't matter if your primary key is an automatically incremental id or a unique field. If you have ssn defined in the parent class, it will be available for searching in all your subclasses.
So a couple of tips here. You can if you want, remove the automatical id and use ssn as your primary key, then doctrine expects that all of your child tables to have that same field defined in them. For performance it may be wise to have an integer instead of a 255 string to do the joins anyway.
If you want to mantain the automated id, you may want to add a unique index to the parent class, that way if you access the classes by that field, you wont get performance slowdowns.
If you want to have the class name to be something and the table name to be something else, use this
But then remember that all the tables that are part of the inheritance should use that name.
Moreover, I normally use doctrine for mapping an existing database and extending it (migrate to doctrine), and if I'm adding a new feature and the model requires so, I create the mapping and tables myself keeping in mind how Doctrines inheritance works. But if you have existing tables that think can be modeled with Inheritance, expect some trouble, and maybe the needs to modify the existing tables.
Hope this helps.