cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject [CONF] Apache Cayenne Documentation > Inheritance Overview
Date Tue, 08 Jun 2010 20:57:00 GMT
    <base href="">
            <link rel="stylesheet" href="/confluence/s/1810/9/1/_/styles/combined.css?spaceKey=CAYDOC&amp;forWysiwyg=true"
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="">Inheritance
    <h4>Page <b>edited</b> by             <a href="">Andrus
                         <h4>Changes (4)</h4>
<div id="page-diffs">
            <table class="diff" cellpadding="0" cellspacing="0">
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h2. Inheritance and ORM <br>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">There
are three common types of inheritance mapping to the database schema in ORM. Cayenne supports
two of them, as described in the following chapters. Here we will provide a general overview
of possible mapping scenarios. Each is useful for different reasons depending on storage criteria,
database optimisation and so on. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">There
are three types of inheritance mapping to the database schema in ORM. Different terms are
used sometimes by different frameworks to describe the implementations of inheritance, but
they refer to the same common concepts: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">||Cayenne||Hibernate||JPA||
<br>|Single table|table-per-class-hierarchy|single table| <br>|Vertical|table-per-subclass|joined|
<br>|Horizontal _(currently unsupported)_|table-per-concrete-class|table per class|
<br> <br>Cayenne supports two of them (single table and vertical), as described
in the following chapters. Here we will provide a general overview of these types of mappings.
<br> <br></td></tr>
            <tr><td class="diff-unchanged" >!inheritance-overview.png! <br>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h2.
Terminology <br> <br>Different terms are used sometimes to describe the implementations
of inheritance: <br> <br>||WebObjects||Hibernate||JPA|| <br>|Single table|table-per-class-hierarchy|single
table| <br>|Horizontal|table-per-concrete-class|table per class| <br>|Vertical|table-per-subclass|joined|
<br> <br></td></tr>
            <tr><td class="diff-unchanged" >h2. Interfaces <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="InheritanceOverview-WhyUseInheritance%3F"></a>Why Use

<p>Inheritance is a powerful OO feature and can significantly simplify your code, but
it does take a little time to fully understand how it works within an ORM framework like Cayenne.
We will use a simple example from school database to illustrate the concepts: a Person could
be either a Student or a Teacher and so in Java you'd want to express these as a Person class
with Student and Tutor as two subclasses. The Java class structure (the object entities) looks
roughly like this:</p>

<p><span class="image-wrap" style=""><img src="/confluence/download/attachments/55796/inheritance-example.png?version=1&amp;modificationDate=1180613216000"
style="border: 0px solid black" /></span>|align=left!</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> <span class="code-keyword">abstract</span>
class Person <span class="code-keyword">extends</span> PersistentObject {}
<span class="code-keyword">public</span> class Teacher <span class="code-keyword">extends</span>
Person {}
<span class="code-keyword">public</span> class Student <span class="code-keyword">extends</span>
Person {}

<p>Some possibilities are immediately obvious: you may wish to write a messaging system
which sends emails to both Students and Teachers. Rather than deal with the two classes separately,
now you can move the emailAddress attribute to the Person superclass. Your messaging framework
can now work with Person, irrespective if they are students, tutors or any other subclasss
of Person. Or perhaps you want to be able to link book loans to both Students and Teachers.
You can do this by moving the relationship with book loans into the Person superclass.</p>

<h2><a name="InheritanceOverview-AbstractorConcreteSuperclass"></a>Abstract
or Concrete Superclass</h2>

<p>Notice that in the example above, Person is an abstract class. That is, you cannot
commit a person who is neither a Student nor a Teacher. But sometimes it is useful to make
the superclass concrete and not abstract. This allows you to store a Person without yet giving
them attributes from either subclass. Perhaps they are simply a person for whom we wish to
store some contact information. Maybe later on they will become a Student and we will add
those attributes. Because Java does not have multiple inheritance, it is not possible for
a person to be a Student and a Teacher at the same time. Interfaces are probably a good way
to address that type of model and will be discussed later.</p>

<h2><a name="InheritanceOverview-InheritanceandORM"></a>Inheritance and

<p>There are three types of inheritance mapping to the database schema in ORM. Different
terms are used sometimes by different frameworks to describe the implementations of inheritance,
but they refer to the same common concepts:</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<th class='confluenceTh'>Cayenne</th>
<th class='confluenceTh'>Hibernate</th>
<th class='confluenceTh'>JPA</th>
<td class='confluenceTd'>Single table</td>
<td class='confluenceTd'>table-per-class-hierarchy</td>
<td class='confluenceTd'>single table</td>
<td class='confluenceTd'>Vertical</td>
<td class='confluenceTd'>table-per-subclass</td>
<td class='confluenceTd'>joined</td>
<td class='confluenceTd'>Horizontal <em>(currently unsupported)</em></td>
<td class='confluenceTd'>table-per-concrete-class</td>
<td class='confluenceTd'>table per class</td>

<p>Cayenne supports two of them (single table and vertical), as described in the following
chapters. Here we will provide a general overview of these types of mappings.</p>

<p><span class="image-wrap" style=""><img src="/confluence/download/attachments/55796/inheritance-overview.png?version=1&amp;modificationDate=1180613226000"
style="border: 0px solid black" /></span></p>

<h3><a name="InheritanceOverview-SingleTableInheritance"></a>Single Table

<p>One database table or view (dbEntity) is used for all the subclasses and the superclass.
So Person, Student and Teacher are all mapped against the one dbEntity. If an attribute appears
in Student but not in Teacher (for example the hasScholarship attribute) then that column
in the database is set to NULL for all Teachers committed. Naturally, the columns found only
in the subclasses cannot be restricted to 'NOT NULL' in the database.</p>

<p>This type of inheritance works well when there are only a few attributes which are
different between the two subclasses and you don't mind having all the records from the subclasses
combined in one table.</p>

<p>In Cayenne modeler you create this type of inheritance by pointing the superclass
and subclass both to the same dbEntity. You must also define a class designator column which
allows Cayenne to determine which subclass any particular record in the table belongs to.
This column can only be NULL if the superclass is not abstract.</p>

<p>Superclass: abstract or concrete<br/>
Class designator column: required<br/>
Primary key: single column shared by superclass and subclass</p>

<p>Single table inheritance mapping in Cayenne is described <a href="/confluence/display/CAYDOC/Modeling+Inheritance"
title="Modeling Inheritance">here</a>.</p>

<h3><a name="InheritanceOverview-Vertical%28JoinedTable%29Inheritance"></a>Vertical
(Joined Table) Inheritance</h3>

<p>This final approach requires one table per subclass plus one table for the superclass.
All attributes found in the superclass are stored in this additional table. This is particularly
useful when you have lots of common attributes or relations to other entities. Perhaps Person
is subclassed by Student, Teacher, Parent, AdminStaff, Visitor and Applicant. But all these
entities are allowed to borrow books from the library. Now, rather than creating 6 relationships
between each of these tables to the Loan table, you can create a single relationship between
Person and Loan.</p>

<p>Superclass: abstract or concrete<br/>
Class designator column: required<br/>
Primary key: in superclass. Copied into subclass to form the one-to-one join.</p>

<h3><a name="InheritanceOverview-Horizontal%28TablePerClass%29Inheritance"></a>Horizontal
(Table Per Class) Inheritance</h3>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td>As of this writing Cayenne does
not support horizontal inheritance, but it may in the future.</td></tr></table></div>

<p>Here you will need one table per subclass. So your database will have Student and
Teacher tables. Any attributes in the Person object entity will need to be present in both
the database tables.</p>

<p>This type of inheritance is best used when there are few attributes which are found
in the superclass. Because the superclass is abstract you cannot have a relationship to other
entities. For instance if you want to relate both Students and Teachers to library Books borrowed,
then it would be useful to have a single relationship from Person to Books. That is possible
in vertical inheritance.</p>

<p>Normally if you use horizontal inheritance you will set your superclass to be abstract,
but this is not a requirement. If it is a concrete class, then it is important to remember
that you cannot create and commit to the database object entities of this superclass, since
Cayenne would not know which table to add the record to. However you are able to create and
commit Students and Teachers, fetch and edit them as concrete Person objects and then commit
them back the database as Person objects, since Cayenne now 'knows' what subclass they belong

<p>Superclass: abstract or concrete (usually abstract)<br/>
Class designator column: not required<br/>
Primary key: in each subclass (unique across all subclasses)</p>

<h2><a name="InheritanceOverview-Interfaces"></a>Interfaces</h2>

<p>Sometimes you don't need inheritance but rather you want Cayenne to give you a simple
way to define an interface for your classes. The regular Student and Teacher classes both
need to implement emailAddress attributes so that you have a consistent way to access that

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> <span class="code-keyword">interface</span>
Address {
	<span class="code-keyword">public</span> <span class="code-object">String</span>
<span class="code-keyword">public</span> class Teacher <span class="code-keyword">extends</span>
PersistentObject <span class="code-keyword">implements</span> Address {}
<span class="code-keyword">public</span> class Student <span class="code-keyword">extends</span>
PersistentObject <span class="code-keyword">implements</span> Address {}
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href=""
class="grey">Change Notification Preferences</a>
        <a href="">View
        <a href="">View
        <a href=";showCommentArea=true#addcomment">Add

View raw message