"Inheritance" is an Object Oriented concept absent in traditional RDBMS. Cayenne however allows to map a hierarchical class tree to a single base table (so called "single table inheritance"). Such mapping is described in detail in the Modeler Guide. The idea of single table inheritance is that a "class" of a database row is determined from the values in one or more columns of the base table. These columns are called "class designator columns".
Consider the following class hierarchy (also used in the Modeler Guide example):
If a class designator column is "PERSON_TYPE", AbstractPerson class should define an attribute (for instance called "personType") that maps to PERSON_TYPE. This attribute is redundant and meanigless in Java, since person type is defined already by the Java class of the object, however we still have to keep it around so that when the new objects are saved, correct PERSON_TYPE data is stored in the database.
Cayenne 3.0 has an ability to inject values of designator columns in new objects automatically. In the example above, if ObjEntity Employee has declared qualifier "personType='EMPLOYEE'", a new Employee instance, created using "context.newObject(Employee.class)" will already have a personType attribute set to "EMPLOYEE".
The mechanism of injecting values of class designator columns currently supports qualifiers of form "attr=value [AND attr=value]*". Thus, flattened paths, db-paths and other than equality comparisons are not supported. Cayenne will try inject as much as possible, e.g. if ObjEntity "GoodEmployee" has qualifier "personType='EMPLOYEE' and salary>10000", only personType attribute value will be injected.
Whenever manual injecting is required, it is a good practice to perform such operations in PrePersist lifecycle listeners or callbacks
When performing SelectQuery on a table that maps to inheritance hierarchy, Cayenne will only return rows that belong to root class of the query and all its subclasses. No superclasses or objects from parallel inheritance branches will be returned. For example executing a SelectQuery with Employee class as root will potentially return a mix of Employees and Managers (who are also Employees of course), but no CustomerContact objects:
The need to determine the correct class for each fetched database row makes queries on entities that use inheritance less efficient than the regular queries. If an application doesn't care about the query root class subclasses, the query can be optimized by explicitly turning off inheritance resolution. If this is done, the example above will return all Managers as instances of Employee class, not Manager class:
|Whenever an object is obtained via a relationship, it is always fully resolved to the lowest possible subclass in an entity inheritance tree.|
|Use setResolvingInherited(false) with caution, and only if you never plan to work with subclasses. The downside of it is that the DataContext may end up with two objects pointing to the same database row, thus violating uniquing principle. With the above example, this may happen if at a later time user decides to fetch Managers directly, or if a Manager object is obtained via a relationship.|