From c7a5a695d367be433cd9aa28060bb352ce3c1bbd Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Thu, 17 Jun 2010 12:03:01 -0400 Subject: [PATCH] [DDC-246] Added section showing DQL examples when dealing with SINGLE_TABLE and JOINED inheritance since it affects the generated SQL of a DQL query. --- manual/en/dql-doctrine-query-language.txt | 117 ++++++++++++++++++++++ manual/en/inheritance-mapping.txt | 2 +- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/manual/en/dql-doctrine-query-language.txt b/manual/en/dql-doctrine-query-language.txt index ab77e1476..0ef794994 100644 --- a/manual/en/dql-doctrine-query-language.txt +++ b/manual/en/dql-doctrine-query-language.txt @@ -452,6 +452,123 @@ We will register the function by calling and can then use it: \Doctrine\ORM\Query\Parser::registerNumericFunction('FLOOR', 'MyProject\Query\MysqlFloor'); $dql = "SELECT FLOOR(person.salary * 1.75) FROM CompanyPerson person"; +++ Querying Inherited Classes + +This section demonstrates how you can query inherited classes and what type of results +to expect. + ++++ Single Table + +[Single Table Inheritance](http://martinfowler.com/eaaCatalog/singleTableInheritance.html) is an inheritance mapping strategy where all classes of a hierarchy are mapped to a single database table. In order to distinguish which row represents which type in the hierarchy a so-called discriminator column is used. + +First we need to setup an example set of entities to use. In this scenario it is a generic +Person and Employee example: + + [php] + namespace Entities; + + /** + * @Entity + * @InheritanceType("SINGLE_TABLE") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) + */ + class Person + { + /** + * @Id @Column(type="integer") + * @GeneratedValue + */ + protected $id; + + /** + * @Column(type="string", length=50) + */ + protected $name; + + // ... + } + + /** + * @Entity + */ + class Employee extends Person + { + /** + * @Column(type="string", length=50) + */ + private $department; + + // ... + } + +First notice that the generated SQL to create the tables for these entities looks like +the following: + + [sql] + CREATE TABLE Person (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(50) NOT NULL, discr VARCHAR(255) NOT NULL, department VARCHAR(50) NOT NULL) + +Now when persist a new `Employee` instance it will set the discriminator value for us +automatically: + + [php] + $employee = new \Entities\Employee(); + $employee->setName('test'); + $employee->setDepartment('testing'); + $em->persist($employee); + $em->flush(); + +Now lets run a simple query to retrieve the `Employee` we just created: + + [php] + $query = $em->createQuery('select e from Entities\Employee e where e.name = ?1'); + $query->setParameter('1', 'test'); + +If we check the generated SQL you will notice it has some special conditions added to +ensure that we will only get back `Employee` entities: + + [php] + echo $query->getSql(); + + // SELECT p0_.id AS id0, p0_.name AS name1, p0_.department AS department2, p0_.discr AS discr3 FROM Person p0_ WHERE (p0_.name = ?) AND p0_.discr IN ('employee') + ++++ Class Table Inheritance + +[Class Table Inheritance](http://martinfowler.com/eaaCatalog/classTableInheritance.html) is an inheritance mapping strategy where each class in a hierarchy is mapped to several tables: its own table and the tables of all parent classes. The table of a child class is linked to the table of a parent class through a foreign key constraint. +Doctrine 2 implements this strategy through the use of a discriminator column in the topmost table of the hierarchy because this is the easiest way to achieve polymorphic queries with Class Table Inheritance. + +The example for class table inheritance is the same as single table, you just need to +change the inheritance type from `SINGLE_TABLE` to `JOINED`: + + /** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) + */ + class Person + { + // ... + } + +Now take a look at the SQL which is generated to create the table, you'll notice some +differences: + + [sql] + CREATE TABLE Person (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, discr VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; + CREATE TABLE Employee (id INT NOT NULL, department VARCHAR(50) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; + ALTER TABLE Employee ADD FOREIGN KEY (id) REFERENCES Person(id) ON DELETE CASCADE + +* The data is split between two tables +* A foreign key exists between the two tables + +Now if were to insert the same `Employee` as we did in the `SINGLE_TABLE` example and run +the same example query it will generate different SQL joining the `Person` information +automatically for you: + + [sql] + SELECT p0_.id AS id0, p0_.name AS name1, e1_.department AS department2, p0_.discr AS discr3 FROM Employee e1_ INNER JOIN Person p0_ ON e1_.id = p0_.id WHERE p0_.name = ? + ++ The Query class An instance of the `Doctrine\ORM\Query` class represents a DQL query. You create a Query instance be calling `EntityManager#createQuery($dql)`, passing the DQL query string. Alternatively you can create an empty `Query` instance and invoke `Query#setDql($dql)` afterwards. Here are some examples: diff --git a/manual/en/inheritance-mapping.txt b/manual/en/inheritance-mapping.txt index 70a87afa4..b6a4b49ef 100644 --- a/manual/en/inheritance-mapping.txt +++ b/manual/en/inheritance-mapping.txt @@ -97,7 +97,7 @@ This strategy is very efficient for querying across all types in the hierarchy o ++ Class Table Inheritance [Class Table Inheritance](http://martinfowler.com/eaaCatalog/classTableInheritance.html) is an inheritance mapping strategy where each class in a hierarchy is mapped to several tables: its own table and the tables of all parent classes. The table of a child class is linked to the table of a parent class through a foreign key constraint. -Doctrine 2 implements this strategy through the use of a discriminator column in the topmost table of the hieararchy because this is the easiest way to achieve polymorphic queries with Class Table Inheritance. +Doctrine 2 implements this strategy through the use of a discriminator column in the topmost table of the hierarchy because this is the easiest way to achieve polymorphic queries with Class Table Inheritance. Example: