cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Cayenne Documentation > Modeling Single Table Inheritance
Date Tue, 27 Jul 2010 11:58:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1810/9/1/_/styles/combined.css?spaceKey=CAYDOC&amp;forWysiwyg=true"
type="text/css">
    </head>
<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="https://cwiki.apache.org/confluence/display/CAYDOC/Modeling+Single+Table+Inheritance">Modeling
Single Table Inheritance</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~andrus">Andrus
Adamchik</a>
    </h4>
        <br/>
                         <h4>Changes (19)</h4>
                                 
    
<div id="page-diffs">
            <table class="diff" cellpadding="0" cellspacing="0">
            <tr><td class="diff-unchanged" >h2. Modeling Single Table Inheritance
<br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">In
a single table inheritance mapping all classes in the hierarchy are mapped to the same base
table. One or more columns in the base table are usually assumed to be &quot;class designator
columns&quot;. Their values determine what object class to use when a fetched row is converted
to a persistent object.  <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Let&#39;s
look at a specific example shown below. An online bookstore may be selling regular paper books
and electronic books. Both share a number of common attributes placed in a common superclass
&quot;Book&quot;, but also have a number of specific attributes found only in each
book distribution format: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3.
Creating ObjEntity Hierarchy <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">!single-table-inheritance.png!
<br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Consider
the following class hierarchy that we want to map to a PERSON table: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">bq.
As with many other ORM inheritance examples, this one is contrived and oversimplified. In
a real bookstore it is likely that the same book is available in both formats, so mapping
this inheritance hierarchy as a composition may be more appropriate, but let&#39;s stick
with this example for simplicity sake. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">!inheritance-diagram.jpg!
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">As
you see, a &quot;BOOK&quot; table contains attributes from superclass and all subclasses,
plus it has the ID (primary key) and a &quot;TYPE&quot; column which will be used
as a &quot;discriminator colum&quot; to determine which sublcass is stored in each
row. Mapping of this inheritance hierarchy, just like mapping a single class, starts by creating
a DbEntity for the &quot;BOOK&quot; table: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">For
each of the four Java classes one may create individual ObjEntities, however only AbstractPerson
entity would map directly to the underlying &quot;PERSON&quot; DbEntity. For the rest
instead of selecting a value from the &quot;Table/View&quot; dropdown, a corresponding
&quot;super entity&quot; from the &quot;Inheritance&quot; dropdown should
be selected. Note that when an entity inherits from another entity, a list of inherited attributes
and relationships shows up as read only information under the corresponding tabs. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">!book-dbentity.png!
<br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h4.
Defining Class Qualifier <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Now
let&#39;s create a superclass &quot;Book&quot;, mapping only the columns that
should be in the superclass (you can do it by clicking on &quot;Create ObjEntity&quot;
icon on the DbEntity toolbar, and then removing unneeded subclass attributes). The next step
is to create two subclasses. For each one of them, create a new ObjEntity, then under &quot;Inheritance&quot;
dropdown specify &quot;Book&quot; as a superclass. This automatically selects &quot;Table/View&quot;
to be &quot;BOOK&quot;.  <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Afer
creating entity inheritance tree, it is important to configure how the entities differ from
each other, so that later when the data is fetched, Cayenne would know which class to instantiate.
This is achieved by using entity qualifiers described earlier. Usually all entities in the
hierarchy, except for the root, require such qualifier. It should be created in such a way
that it completely defines a given entity without considering any subclasses or superclasses.
In the example above, if the possible values of the class designator column are &quot;EMPLOYEE&quot;,
&quot;MANAGER&quot;, &quot;CUSTOMER&quot;, the following qualifiers might
be used: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">While
Book is an abstract class and we did not specify entity qualifier for it (we could if it wasn&#39;t
abstract), PaperBook and EBook both require &quot;Qualifier&quot; field to be populated.
Let&#39;s assume that &quot;E&quot; is a designator for e-books, and &quot;P&quot;
- for the paper books, then respective qualifiers would look like this: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">||ObjEntity||Qualifier||Final
Qualifier Generated by Cayenne for SelectQuery|| <br>|AbstractPerson|none|none| <br>|CustomerContact|personType
= &#39;CUSTOMER&#39;|personType = &#39;CUSTOMER&#39;| <br>|Employee|personType
= &#39;EMPLOYEE&#39;|personType = &#39;EMPLOYEE&#39; or personType = &#39;MANAGER&#39;|
<br>|Manager|personType = &#39;MANAGER&#39;|personType = &#39;MANAGER&#39;|
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
{{type = &#39;E&#39;}} <br>* {{type = &#39;P&#39;}} <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{note:title=Qualifiers
Note} <br>Qualifiers are not inherited! When defining qualifiers for inheritance purposes
keep in mind that the actual qualifier built by Cayenne will include the qualifier of a root
entity and qualifiers of all its known subentities joined using &quot;or&quot; operator,
as shown in the above example.  <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">{note}</span>
<span class="diff-added-words"style="background-color: #dfd;">!book-qualifier.png!</span>
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>bq. Unlike some other ORMs, Cayenne is really flexible about the semantics of discriminator
columns. Qualifier can be any valid Cayenne expression, as long as it doesn&#39;t span
any relationships (i.e. uses columns of the root table only). It doesn&#39;t have to be
a single collumn, it can contain less or greater expressions. E.g. &quot;{{price &gt;
500}}&quot;, &quot;{{type = &#39;E&#39; and sizeMB &lt; 1000}}&quot;,
etc. Note however that if the expression is not settable (e.g. when using &lt; or &gt;),
Cayenne won&#39;t be able to guess the right values on insert and the user application
must provide those values explicitly.  <br> <br>bq. Also note that Qualifiers
are not inherited. When defining qualifiers for inheritance purposes keep in mind that a fetch
qualifier built by Cayenne will include the qualifier of a root entity of a query and qualifiers
of all its known subentities joined using &quot;or&quot; operator.  <br> <br>Finally
switch to &quot;Attributes&quot; tab and in addition to the already shown inherited
attributes, add entity-specific attributes. Note that Relationships can also be inherited,
or subclass-specific (not shown in our example). <br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="ModelingSingleTableInheritance-ModelingSingleTableInheritance"></a>Modeling
Single Table Inheritance</h2>

<p>Let's look at a specific example shown below. An online bookstore may be selling
regular paper books and electronic books. Both share a number of common attributes placed
in a common superclass "Book", but also have a number of specific attributes found only in
each book distribution format:</p>

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

<blockquote><p>As with many other ORM inheritance examples, this one is contrived
and oversimplified. In a real bookstore it is likely that the same book is available in both
formats, so mapping this inheritance hierarchy as a composition may be more appropriate, but
let's stick with this example for simplicity sake.</p></blockquote>

<p>As you see, a "BOOK" table contains attributes from superclass and all subclasses,
plus it has the ID (primary key) and a "TYPE" column which will be used as a "discriminator
colum" to determine which sublcass is stored in each row. Mapping of this inheritance hierarchy,
just like mapping a single class, starts by creating a DbEntity for the "BOOK" table:</p>

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

<p>Now let's create a superclass "Book", mapping only the columns that should be in
the superclass (you can do it by clicking on "Create ObjEntity" icon on the DbEntity toolbar,
and then removing unneeded subclass attributes). The next step is to create two subclasses.
For each one of them, create a new ObjEntity, then under "Inheritance" dropdown specify "Book"
as a superclass. This automatically selects "Table/View" to be "BOOK". </p>

<p>While Book is an abstract class and we did not specify entity qualifier for it (we
could if it wasn't abstract), PaperBook and EBook both require "Qualifier" field to be populated.
Let's assume that "E" is a designator for e-books, and "P" - for the paper books, then respective
qualifiers would look like this:</p>

<ul>
	<li><tt>type = 'E'</tt></li>
	<li><tt>type = 'P'</tt></li>
</ul>


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

<blockquote><p>Unlike some other ORMs, Cayenne is really flexible about the semantics
of discriminator columns. Qualifier can be any valid Cayenne expression, as long as it doesn't
span any relationships (i.e. uses columns of the root table only). It doesn't have to be a
single collumn, it can contain less or greater expressions. E.g. "<tt>price &gt;
500</tt>", "<tt>type = 'E' and sizeMB &lt; 1000</tt>", etc. Note however
that if the expression is not settable (e.g. when using &lt; or &gt;), Cayenne won't
be able to guess the right values on insert and the user application must provide those values
explicitly. </p></blockquote>

<blockquote><p>Also note that Qualifiers are not inherited. When defining qualifiers
for inheritance purposes keep in mind that a fetch qualifier built by Cayenne will include
the qualifier of a root entity of a query and qualifiers of all its known subentities joined
using "or" operator. </p></blockquote>

<p>Finally switch to "Attributes" tab and in addition to the already shown inherited
attributes, add entity-specific attributes. Note that Relationships can also be inherited,
or subclass-specific (not shown in our example).</p>



    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAYDOC/Modeling+Single+Table+Inheritance">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=10528&revisedVersion=5&originalVersion=4">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAYDOC/Modeling+Single+Table+Inheritance?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message