| 1 |
lars |
1 |
<com:TContent ID="body">
|
|
|
2 |
<h1>The Big Picture</h1>
|
|
|
3 |
<p>SQLMap is a simple but complete framework that makes it easy for you to map
|
|
|
4 |
your objects to your SQL statements or stored procedures. The goal of the
|
|
|
5 |
SQLMap framework is to obtain 80% of data access functionality using only
|
|
|
6 |
20% of the code.</p>
|
|
|
7 |
|
|
|
8 |
<h1>What does it do?</h1>
|
|
|
9 |
<p>Developers often create maps between objects within an application. One
|
|
|
10 |
definition of a Mapper is an "object that sets up communication between two
|
|
|
11 |
independent objects." A Data Mapper is a "layer of mappers that moves data
|
|
|
12 |
between objects and a database while keeping them independent of each other
|
|
|
13 |
and the mapper itself." [Patterns of Enterprise Architecture, ISBN
|
|
|
14 |
0-321-12742-0].</p>
|
|
|
15 |
|
|
|
16 |
<p>You provide the database and the objects; SQLMap provides the mapping layer
|
|
|
17 |
that goes between the two.</p>
|
|
|
18 |
|
|
|
19 |
<h1>How does it work?</h1>
|
|
|
20 |
|
|
|
21 |
<p>Your programming platform already provides a capable library for accessing
|
|
|
22 |
databases, whether through SQL statements or stored procedures. But developers
|
|
|
23 |
find several things are still hard to do well when using "stock" PHP
|
|
|
24 |
function including:</p>
|
|
|
25 |
|
|
|
26 |
<p>Separating SQL code from programming code Passing input parameters to the
|
|
|
27 |
library classes and extracting the output Separating data access classes from
|
|
|
28 |
business logic classes Caching often-used data until it changes Managing
|
|
|
29 |
transactions and many more -- by using XML documents to create a mapping
|
|
|
30 |
between a plain-old object and a SQL statement or a stored procedure. The
|
|
|
31 |
"plain-old object" can be any PHP object.</p>
|
|
|
32 |
|
|
|
33 |
<p class="tip"><b class="tip">Tip:</b>
|
|
|
34 |
The object does not need to be part of a special object hierarchy or implement
|
|
|
35 |
a special interface. (Which is why we call them "plain-old" objects.)
|
|
|
36 |
Whatever you are already using should work just fine.
|
|
|
37 |
</p>
|
|
|
38 |
|
|
|
39 |
<img src=<%~ diagram.png %> alt="SQLMap DataMapper work flow" id="fig:diagram.png" class="figure"/>
|
|
|
40 |
<div class="caption"><b>Figure 1:</b> SQLMap DataMapper work flow</div>
|
|
|
41 |
|
|
|
42 |
<p>Here's a high level description of the work flow shown in the figure above:
|
|
|
43 |
Provide a parameter, either as an object or a
|
|
|
44 |
primitive type. The parameter can be used to set runtime values in your SQL
|
|
|
45 |
statement or stored procedure. If a runtime value is not needed, the parameter
|
|
|
46 |
can be omitted.</p>
|
|
|
47 |
|
|
|
48 |
<p>Execute the mapping by passing the parameter and the name you gave the
|
|
|
49 |
statement or procedure in your XML descriptor. This step is where the magic
|
|
|
50 |
happens. The framework will prepare the SQL statement or stored procedure, set
|
|
|
51 |
any runtime values using your parameter, execute the procedure or statement,
|
|
|
52 |
and return the result.</p>
|
|
|
53 |
|
|
|
54 |
<p>In the case of an update, the number of rows affected is returned. In the case
|
|
|
55 |
of a query, a single object, or a collection of objects is returned. Like the
|
|
|
56 |
parameter, the result object, or collection of objects, can be a plain-old
|
|
|
57 |
object or a primitive type.</p>
|
|
|
58 |
|
|
|
59 |
<p>So, what does all this look like in your source code? Here's how you might
|
|
|
60 |
code the insert of a "lineItem" object into your database.</p>
|
|
|
61 |
|
|
|
62 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
63 |
TMapper::instance()->insert("InsertLineItem", $lineItem);
|
|
|
64 |
</com:TTextHighlighter>
|
|
|
65 |
|
|
|
66 |
<p>If your database is generating the primary keys, the generated key can be
|
|
|
67 |
returned from the same method call, like this:</p>
|
|
|
68 |
|
|
|
69 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
70 |
$myKey = TMapper::instance()->insert("InsertLineItem", $lineItem);
|
|
|
71 |
</com:TTextHighlighter>
|
|
|
72 |
|
|
|
73 |
<p>The following example shows an XML descriptor for "InsertLineItem".
|
|
|
74 |
<com:TTextHighlighter Language="xml" CssClass="source">
|
|
|
75 |
<insert id="InsertLineItem" parameterClass="LineItem">
|
|
|
76 |
INSERT INTO [LinesItem]
|
|
|
77 |
(Order_Id, LineItem_LineNum, Item_Id, LineItem_Quantity, LineItem_UnitPrice)
|
|
|
78 |
VALUES
|
|
|
79 |
(#Order.Id#, #LineNumber#, #Item.Id#, #Quantity#, #Item.ListPrice#)
|
|
|
80 |
<selectKey type="post" resultClass="int" property="Id" >
|
|
|
81 |
select @@IDENTITY as value
|
|
|
82 |
</selectKey>
|
|
|
83 |
</insert>
|
|
|
84 |
</com:TTextHighlighter>
|
|
|
85 |
</p>
|
|
|
86 |
|
|
|
87 |
<p>The <tt><selectKey></tt> stanza returns an auto-generated key from a SQL Server
|
|
|
88 |
database (for example). If you need to select multiple rows, SQLMap can return
|
|
|
89 |
a list of objects, each mapped to a row in the result set:
|
|
|
90 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
91 |
$productList = Mapper::instance()->queryForList("selectProduct",$categoryKey);
|
|
|
92 |
</com:TTextHighlighter>
|
|
|
93 |
Or just one, if that's all you need:
|
|
|
94 |
<com:TTextHighlighter Language="php" CssClass="source">
|
|
|
95 |
$product = Mapper::instance()->queryForObject("selectProduct",$categoryKey);
|
|
|
96 |
</com:TTextHighlighter>
|
|
|
97 |
</p>
|
|
|
98 |
|
|
|
99 |
<p>Of course, there's more, but this is SQLMap from 10,000 meters. (For a longer,
|
|
|
100 |
gentler introduction, see the <a href="?page=Tutorial.TestFirst">Tutorial</a>.)
|
|
|
101 |
The <a href=" ?page=Manual.DataMapperConfiguration">Data Map definition</a> files describes
|
|
|
102 |
where the statement for "InsertLineItem" would
|
|
|
103 |
be defined. The <a href="?page=Manual.Installing">Installation and Setup</a> section describes
|
|
|
104 |
the "bootstrap" configuration file that exposes SQLMap to your application.</p>
|
|
|
105 |
|
|
|
106 |
<h1>Is SQLMap the best choice for my project?</h1>
|
|
|
107 |
<p>SQLMap is a Data Mapping tool. Its role is to map the columns of a database
|
|
|
108 |
query (including a stored procedure) to the properties of an object. If your
|
|
|
109 |
application is based on business objects (including array or lists of
|
|
|
110 |
objects), then SQLMap can be a good choice. SQLMap is an even better choice
|
|
|
111 |
when your application is layered, so that that the business layer is distinct
|
|
|
112 |
from the user-interface layer.</p>
|
|
|
113 |
|
|
|
114 |
<p>Under these circumstances, another good choice would be an Object/Relational
|
|
|
115 |
Mapping tool (OR/M tool), like [...]. Other products in this category are
|
|
|
116 |
[...] and [...] . An OR/M tool generates all or most of the SQL for you,
|
|
|
117 |
either beforehand or at runtime. These products are called OR/M tools because
|
|
|
118 |
they try to map an object graph to a relational schema.</p>
|
|
|
119 |
|
|
|
120 |
<p>SQLMap is not an OR/M tool. SQLMap helps you map objects to stored procedures
|
|
|
121 |
or SQL statements. The underlying schema is irrelevant. An OR/M tool is great
|
|
|
122 |
if you can map your objects to tables. But they are not so great if your
|
|
|
123 |
objects are stored as a relational view rather than as a table. If you can
|
|
|
124 |
write a statement or procedure that exposes the columns for your object,
|
|
|
125 |
regardless of how they are stored, SQLMap can do the rest.</p>
|
|
|
126 |
|
|
|
127 |
<p>So, how do you decide whether to OR/M or to DataMap? As always, the best
|
|
|
128 |
advice is to implement a representative part of your project using either
|
|
|
129 |
approach, and then decide. But, in general, OR/M is a good thing when you
|
|
|
130 |
<ul>
|
|
|
131 |
<li>Have complete control over your database implementation.</li>
|
|
|
132 |
<li>Do not have a Database Administrator or SQL guru on the team.</li>
|
|
|
133 |
<li>Need to model the problem domain outside the database as an object graph.</li>
|
|
|
134 |
</ul>
|
|
|
135 |
Likewise, the best time to use a Data Mapper, like SQLMap, is when:
|
|
|
136 |
<ul>
|
|
|
137 |
<li>You do not have complete control over the database implementation, or want to
|
|
|
138 |
continue to access a legacy database as it is being refactored.</li>
|
|
|
139 |
<li>You have database administrators or SQL gurus on the team.</li>
|
|
|
140 |
<li>The database is being used to model the problem domain, and the application's
|
|
|
141 |
primary role is to help the client use the database model.</li>
|
|
|
142 |
</ul>
|
|
|
143 |
</p>
|
|
|
144 |
|
|
|
145 |
<p>In the end, you have to decide what's best for your project. If a OR/M tool
|
|
|
146 |
works better for you, that's great! If your next project has different needs,
|
|
|
147 |
then we hope you give SQLMap another look. If SQLMap works for you now:
|
|
|
148 |
Excellent!</p>
|
|
|
149 |
|
|
|
150 |
|
|
|
151 |
</com:TContent>
|