summaryrefslogtreecommitdiff
path: root/demos/sqlmap/protected/pages/Manual/InheritanceMapping.page
blob: 0458a29193cf69dd6b99d3466df8396abe9fc8a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<com:TContent ID="body">

<h1>Inheritance Mapping</h1> 
<p>The SQLMap PHP DataMapper supports the implementation
of object-oriented inheritance (subclassing) in your object model. There are
several developer options for mapping entity classes and subclasses to
database results:</p>

<p>You can use the most
efficient mapping strategies from a SQL and query performance perspective when
using the inheritance mappings of the DataMapper. To implement an inheritance
mapping, the <tt>resultMap</tt> must define one or more columns in your query's
resultset that will serve to identify which <tt>resultMap</tt> should be used to map
each result record to a specific subclass. In many cases, you will use one
column value for the DataMapper to use in identifying the proper resultMap and
subclass. This column is known as a discriminator.</p>

<p>For example, we have a table defined in a database that contains <tt>Document</tt>
records. There are five table columns used to store Document IDs, Titles,
Types, PageNumbers, and Cities. Perhaps this table belongs to a legacy
database, and we need to create an application using this table with a domain
model that defines a class hierarchy of different types of Documents. Or
perhaps we are creating a new application and database and just want to
persist the data found in a set of related classes into one table. In either
case, the DataMapper's inheritance mapping feature can help.</p>

<com:TTextHighlighter Language="sql" CssClass="source">
CREATE TABLE Documents (
    Document_ID int NOT NULL ,
    Document_Title varchar(32) NULL ,
    Document_Type varchar(32)  NULL ,
    Document_PageNumber int NULL  ,
    Document_City varchar(32)  NULL
)
</com:TTextHighlighter>

<p>To illustrate this, let's take a look at a few example classes shown below
that have a relationship through inheritance and whose properties can be
persisted into our Documents table. First, we have a base Document class that
has Id and Title properties. Next, we have a Book class that inherits from
Document and contains an additional property called PageNumber. Last, we have
a Newspaper class that also inherits from Document and contains a City
property.</p>

<com:TTextHighlighter Language="php" CssClass="source">
class Document 
{
    public $ID = -1;
    public $Title = '';
}

class Book extends Document
{
    public $PageNumber = -1;
}

class Newspaper extends Document 
{
    public $City = '';
}
</com:TTextHighlighter>

<p>Now that we have our classes and database table, we can start working on our
mappings. We can create one <tt>&lt;select&gt;</tt> statement that returns all columns in the
table. To help the DataMapper discriminate between the different Document
records, we're going to indicate that the <tt>Document_Type</tt> column holds values
that will distinguish one record from another for mapping the results into our
class hierarchy.</p>

<com:TTextHighlighter Language="xml" CssClass="source">
<select id="GetAllDocument" resultMap="document">
   select
     Document_Id, Document_Title, Document_Type,
     Document_PageNumber, Document_City
   from Documents
   order by Document_Type, Document_Id
</select>

<resultMap id="document" class="Document">
  <result property="Id" column="Document_ID"/>
  <result property="Title" column="Document_Title"/>
  <discriminator column="Document_Type" type="string"/>
  <subMap value="Book" resultMapping="book"/>
  <subMap value="Newspaper" resultMapping="newspaper"/>
</resultMap>

<resultMap id="book" class="Book" extends="document">
  <property="PageNumber" column="Document_PageNumber"/>
</resultMap>

<resultMap id="newspaper" class="Newspaper"  extends="document">
  <property="City" column="Document_City"/>
</resultMap>
</com:TTextHighlighter>

<p>The DataMapper compares the data found in the discriminator column to the
different <tt>&lt;submap&gt;</tt> values using the column value's string equivalence. Based
on this string value, SQLMap DataMapper will use the resultMap named "<tt>Book</tt>" or
"<tt>Newspaper</tt>" as defined in the <tt>&lt;submap&gt;</tt> elements or it will use the 
"parent" resultMap "<tt>Document</tt>" if neither of the submap values satisfy the comparison.
With these resultMaps, we can implement an object-oriented inheritance mapping
to our database table.</p>

<p>If you want to use custom logic, you can use the typeHandler attribute of the
<tt>&lt;discriminator&gt;</tt> element to specify a custom type handler for the discriminator
column.</p>

<com:TTextHighlighter Language="xml" CssClass="source">
  <resultMap id="document-custom-formula" class="Document">
    <result property="Id" column="Document_ID"/>
    <result property="Title" column="Document_Title"/>
    <discriminator column="Document_Type" typeHandler="CustomInheritance"/>
    <subMap value="Book" resultMapping="book"/>
    <subMap value="Newspaper" resultMapping="newspaper"/>
  </resultMap>
</resultMaps>
</com:TTextHighlighter>

<p>The value of the <tt>typeHandler</tt> attribute specifies which of our classes
implements the <tt>ITypeHandlerCallback</tt> interface. This interface furnishes a
<tt>getResult</tt> method for coding custom logic to read the column result value and
return a value for the DataMapper to use in its comparison to the resultMap's
defined <tt>&lt;submap&gt;</tt> values.</p>

<com:TTextHighlighter Language="php" CssClass="source">
class CustomInheritance implements ITypeHandlerCallback 
{
    public function getResult($type)
    {
        if ($type=="Monograph" || $type=="Book")
            return "Book";
        else if ($type=="Tabloid" || $type=="Broadsheet" || $type=="Newspaper")
            return "Newspaper";
        else
            return "Document";
    }
    
    public function getParameter($object)
    {
        throw new Exception('unimplemented');
    }
    
    public function createNewInstance()
    {
        throw new Exception('unimplemented');
    }
}
</com:TTextHighlighter>

</com:TContent>