| 1 |
lars |
1 |
<com:TContent ID="body">
|
|
|
2 |
|
|
|
3 |
<h1>Inheritance Mapping</h1>
|
|
|
4 |
<p>The SQLMap PHP DataMapper supports the implementation
|
|
|
5 |
of object-oriented inheritance (subclassing) in your object model. There are
|
|
|
6 |
several developer options for mapping entity classes and subclasses to
|
|
|
7 |
database results:</p>
|
|
|
8 |
|
|
|
9 |
<p>You can use the most
|
|
|
10 |
efficient mapping strategies from a SQL and query performance perspective when
|
|
|
11 |
using the inheritance mappings of the DataMapper. To implement an inheritance
|
|
|
12 |
mapping, the <tt>resultMap</tt> must define one or more columns in your query's
|
|
|
13 |
resultset that will serve to identify which <tt>resultMap</tt> should be used to map
|
|
|
14 |
each result record to a specific subclass. In many cases, you will use one
|
|
|
15 |
column value for the DataMapper to use in identifying the proper resultMap and
|
|
|
16 |
subclass. This column is known as a discriminator.</p>
|
|
|
17 |
|
|
|
18 |
<p>For example, we have a table defined in a database that contains <tt>Document</tt>
|
|
|
19 |
records. There are five table columns used to store Document IDs, Titles,
|
|
|
20 |
Types, PageNumbers, and Cities. Perhaps this table belongs to a legacy
|
|
|
21 |
database, and we need to create an application using this table with a domain
|
|
|
22 |
model that defines a class hierarchy of different types of Documents. Or
|
|
|
23 |
perhaps we are creating a new application and database and just want to
|
|
|
24 |
persist the data found in a set of related classes into one table. In either
|
|
|
25 |
case, the DataMapper's inheritance mapping feature can help.</p>
|
|
|
26 |
|
|
|
27 |
<com:TTextHighlighter Language="sql" CssClass="source">
|
|
|
28 |
CREATE TABLE Documents (
|
|
|
29 |
Document_ID int NOT NULL ,
|
|
|
30 |
Document_Title varchar(32) NULL ,
|
|
|
31 |
Document_Type varchar(32) NULL ,
|
|
|
32 |
Document_PageNumber int NULL ,
|
|
|
33 |
Document_City varchar(32) NULL
|
|
|
34 |
)
|
|
|
35 |
</com:TTextHighlighter>
|
|
|
36 |
|
|
|
37 |
<p>To illustrate this, let's take a look at a few example classes shown below
|
|
|
38 |
that have a relationship through inheritance and whose properties can be
|
|
|
39 |
persisted into our Documents table. First, we have a base Document class that
|
|
|
40 |
has Id and Title properties. Next, we have a Book class that inherits from
|
|
|
41 |
Document and contains an additional property called PageNumber. Last, we have
|
|
|
42 |
a Newspaper class that also inherits from Document and contains a City
|
|
|
43 |
property.</p>
|
|
|
44 |
|
|
|
45 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
46 |
class Document
|
|
|
47 |
{
|
|
|
48 |
public $ID = -1;
|
|
|
49 |
public $Title = '';
|
|
|
50 |
}
|
|
|
51 |
|
|
|
52 |
class Book extends Document
|
|
|
53 |
{
|
|
|
54 |
public $PageNumber = -1;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
class Newspaper extends Document
|
|
|
58 |
{
|
|
|
59 |
public $City = '';
|
|
|
60 |
}
|
|
|
61 |
</com:TTextHighlighter>
|
|
|
62 |
|
|
|
63 |
<p>Now that we have our classes and database table, we can start working on our
|
|
|
64 |
mappings. We can create one <tt><select></tt> statement that returns all columns in the
|
|
|
65 |
table. To help the DataMapper discriminate between the different Document
|
|
|
66 |
records, we're going to indicate that the <tt>Document_Type</tt> column holds values
|
|
|
67 |
that will distinguish one record from another for mapping the results into our
|
|
|
68 |
class hierarchy.</p>
|
|
|
69 |
|
|
|
70 |
<com:TTextHighlighter Language="xml" CssClass="source">
|
|
|
71 |
<select id="GetAllDocument" resultMap="document">
|
|
|
72 |
select
|
|
|
73 |
Document_Id, Document_Title, Document_Type,
|
|
|
74 |
Document_PageNumber, Document_City
|
|
|
75 |
from Documents
|
|
|
76 |
order by Document_Type, Document_Id
|
|
|
77 |
</select>
|
|
|
78 |
|
|
|
79 |
<resultMap id="document" class="Document">
|
|
|
80 |
<result property="Id" column="Document_ID"/>
|
|
|
81 |
<result property="Title" column="Document_Title"/>
|
|
|
82 |
<discriminator column="Document_Type" type="string"/>
|
|
|
83 |
<subMap value="Book" resultMapping="book"/>
|
|
|
84 |
<subMap value="Newspaper" resultMapping="newspaper"/>
|
|
|
85 |
</resultMap>
|
|
|
86 |
|
|
|
87 |
<resultMap id="book" class="Book" extends="document">
|
|
|
88 |
<property="PageNumber" column="Document_PageNumber"/>
|
|
|
89 |
</resultMap>
|
|
|
90 |
|
|
|
91 |
<resultMap id="newspaper" class="Newspaper" extends="document">
|
|
|
92 |
<property="City" column="Document_City"/>
|
|
|
93 |
</resultMap>
|
|
|
94 |
</com:TTextHighlighter>
|
|
|
95 |
|
|
|
96 |
<p>The DataMapper compares the data found in the discriminator column to the
|
|
|
97 |
different <tt><submap></tt> values using the column value's string equivalence. Based
|
|
|
98 |
on this string value, SQLMap DataMapper will use the resultMap named "<tt>Book</tt>" or
|
|
|
99 |
"<tt>Newspaper</tt>" as defined in the <tt><submap></tt> elements or it will use the
|
|
|
100 |
"parent" resultMap "<tt>Document</tt>" if neither of the submap values satisfy the comparison.
|
|
|
101 |
With these resultMaps, we can implement an object-oriented inheritance mapping
|
|
|
102 |
to our database table.</p>
|
|
|
103 |
|
|
|
104 |
<p>If you want to use custom logic, you can use the typeHandler attribute of the
|
|
|
105 |
<tt><discriminator></tt> element to specify a custom type handler for the discriminator
|
|
|
106 |
column.</p>
|
|
|
107 |
|
|
|
108 |
<com:TTextHighlighter Language="xml" CssClass="source">
|
|
|
109 |
<resultMap id="document-custom-formula" class="Document">
|
|
|
110 |
<result property="Id" column="Document_ID"/>
|
|
|
111 |
<result property="Title" column="Document_Title"/>
|
|
|
112 |
<discriminator column="Document_Type" typeHandler="CustomInheritance"/>
|
|
|
113 |
<subMap value="Book" resultMapping="book"/>
|
|
|
114 |
<subMap value="Newspaper" resultMapping="newspaper"/>
|
|
|
115 |
</resultMap>
|
|
|
116 |
</resultMaps>
|
|
|
117 |
</com:TTextHighlighter>
|
|
|
118 |
|
|
|
119 |
<p>The value of the <tt>typeHandler</tt> attribute specifies which of our classes
|
|
|
120 |
implements the <tt>ITypeHandlerCallback</tt> interface. This interface furnishes a
|
|
|
121 |
<tt>getResult</tt> method for coding custom logic to read the column result value and
|
|
|
122 |
return a value for the DataMapper to use in its comparison to the resultMap's
|
|
|
123 |
defined <tt><submap></tt> values.</p>
|
|
|
124 |
|
|
|
125 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
126 |
class CustomInheritance implements ITypeHandlerCallback
|
|
|
127 |
{
|
|
|
128 |
public function getResult($type)
|
|
|
129 |
{
|
|
|
130 |
if ($type=="Monograph" || $type=="Book")
|
|
|
131 |
return "Book";
|
|
|
132 |
else if ($type=="Tabloid" || $type=="Broadsheet" || $type=="Newspaper")
|
|
|
133 |
return "Newspaper";
|
|
|
134 |
else
|
|
|
135 |
return "Document";
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
public function getParameter($object)
|
|
|
139 |
{
|
|
|
140 |
throw new Exception('unimplemented');
|
|
|
141 |
}
|
|
|
142 |
|
|
|
143 |
public function createNewInstance()
|
|
|
144 |
{
|
|
|
145 |
throw new Exception('unimplemented');
|
|
|
146 |
}
|
|
|
147 |
}
|
|
|
148 |
</com:TTextHighlighter>
|
|
|
149 |
|
|
|
150 |
</com:TContent>
|