2.3. How does it work?

Your programming platform already provides a capable library for accessing databases, whether through SQL statements or stored procedures. But developers find several things are still hard to do well when using "stock" ADO.NET, including:

iBATIS DataMapper solves these problems -- and many more -- by using XML documents to create a mapping between a plain-old object and a SQL statement or a stored procedure. The "plain-old object" can be a IDictionary or property object.

[Tip]Tip

The object does not need to be part of a special object hierarchy or implement a special interface. (Which is why we call them "plain-old" objects.) Whatever you are already using should work just fine.

iBATIS DataMapper workflow

Figure 2.1. iBATIS DataMapper workflow


Here's a high level description of the workflow diagrammed by Figure 2.1:
  1. Provide a parameter, either as an object or a native type. The parameter can be used to set runtime values in your SQL statement or stored procedure. If a runtime value is not needed, the parameter can be omitted.

  2. Execute the mapping by passing the parameter and the name you gave the statement or procedure in your XML descriptor. This step is where the magic happens. The framework will prepare the SQL statement or stored procedure, set any runtime values using your parameter, execute the procedure or statement, and return the result.

  3. In the case of an update, the number of rows affected is returned. In the case of a query, a single object, or a collection of objects is returned. Like the parameter, the result object, or collection of objects, can be a plain-old object or a native type.

So, what does all this look like in your source code? Here's how you might code the insert of a "lineItem" object into your database:

C#
Mapper.Instance().Insert("InsertLineItem",lineItem);

If your database is generating the primary keys, the generated key can be returned from the same method call, like this:

C#
int myKey = Mapper.Instance().Insert("InsertLineItem",lineItem);

Example 2.1 shows an XML descriptor for "InsertLineItem".

Example 2.1. The "InsertLineItem" descriptor

<insert id="InsertLineItem" parameterClass="LineItem">
  INSERT INTO [LinesItem] 
    (Order_Id, LineItem_LineNum, Item_Id, LineItem_Quantity, LineItem_UnitPrice)
  VALUES
    (#Order.Id#, #LineNumber#, #Item.Id#, #Quantity#, #Item.ListPrice#)
 <selectKey type="post" resultClass="int" property="Id" >
  select @@IDENTITY as value
 </selectKey>
</insert>


The <selectKey> stanza returns an autogenerated key from a SQL Server database (for example).

If you need to select multiple rows, iBATIS can return a list of objects, each mapped to a row in the result set:

C#
IList productList = Mapper.Instance().QueryForList("selectProduct",categoryKey);

Or just one, if that's all you need:

C#
Product product = Mapper.Instance().QueryForObject("SelectProduct",productKey) as Product;

Of course, there's more, but this is iBATIS from 10,000 meters. (For a longer, gentler introduction, see the Tutorial.) Section 3 describes the Data Map definition files -- where the statement for "InsertLineItem" would be defined. The Developers Guide for your platform (Section 4) describes the "bootstrap" configuration file that exposes iBATIS to your application.