Omaha Java Users Group
   March 18, 2008
   Corey A. Spitzer
The Context



              • J2EE (with Spring)
              • OOP
              • SQL Relational Database
What is iBATIS?
Object Oriented



                  Object



  Logic / DAO
                           iBATIS           Database
     Code



                                    Query


                                             Relational
A More Detailed Look

              calls
   Code                       SqlMapClient
                                  insert()
                      loads      update()    calls
                                 delete()
                                  query()


     SQL Maps                                   javax.sql.DataSource
       Queries
     Result Maps

                                                      Magic
                                                      Magic




                                                     Database
The SQL Map Anatomy                               Code
                                                          calls SqlMapClient

                                                          loads                calls

                                                   SQL Maps                            DataSource



<sqlMap namespace="myNamespace">                                                         Magic
                                                                                          Magic

       <resultMap id="myClass" class="full.package.MyClass">
                                                                                       Database
                <result property="foo" column="col1"/>
                <result property="bar" column="col2"/>
                ...
       </resultMap>
       ...
       <!-- ===================================================== -->
       <sql id="myQuery" resultMap="myClass">
                SELECT col1, col2 FROM table1
       </sql>
       ...
</sqlMap>
The Code Anatomy                                 Code
                                                         calls SqlMapClient

                                                         loads                calls
import java.sql.SQLException;
                                                  SQL Maps                            DataSource
import com.ibatis.sqlmap.client.SqlMapClient;
...                                                                                     Magic
                                                                                         Magic

public class MyDAO
                                                                                      Database
{
       private SqlMapClient myDB;


       public void frobnicate(MyObject someObject) throws SQLException
       {
              List<MyClass> list = myDB.queryForList("myQuery");
              Foo myFoo = (Foo)myDB.queryForObject("getFooByID", 1337);
              myDB.update("myQuery3");
              myDB.insert("myQuery4", someObject);
              ...
       }
       ...
}
Any Questions so far?

              calls
   Code                       SqlMapClient
                                  insert()
                      loads      update()    calls
                                 delete()
                                  query()


     SQL Maps                                   javax.sql.DataSource
       Queries
     Result Maps

                                                      Magic
                                                      Magic




                                                     Database
Implicit Mapping

<sqlMap namespace="myNamespace">
       <resultMap id="myClass" class="full.package.Class">
                <result property="foo" column="col1"/>
                <result property="bar" column="col2"/>
                ...
       </resultMap>
       ...
       <!-- ===================================================== -->
       <sql id="myQuery" resultClass="full.package.Class">
                SELECT col1 as foo, col2 as bar FROM table1
       </sql>
       ...
</sqlMap>
Inheritance
    Object Oriented Code                      Relational Database

               Fruit                                     fruits
         id - int                             id - mediumint(7), PK
         dateBought - long                    date_bought - int(11)
                                              type - enum('a', 'o')



                                                       apples
    Apple                Orange               fruit_id - mediumint(7), FK
                                              worm_count - decimal(4,1)
wormCount - float   bioengineered - boolean

                                                      oranges
                                              fruit_id - mediumint(7), FK
                                              bioengineered - bool
Complex Members
  Object Oriented Code             Relational Database

             Cake                             cakes
    id - int                       id - mediumint(7), PK
    flavor - String                flavor - enum('chocolate', ...)
    toppings - List<CakeTopping>


                                   cakes_to_toppings
                                   cake_id - mediumint(7), FK
                                   topping_id - mediumint(7), FK
        CakeTopping
     id - int
     name - String                    cake_toppings
     containsHFCS - boolean
                                   id - mediumint(7), PK
                                   name - varchar(20)
                                   contains_hfcs - bool
Parameters & Dynamic Queries
Custom Type Handlers
public class YesNoBoolTypeHandler implements TypeHandlerCallback {
        public Object getResult(ResultGetter getter) throws SQLException {
                 if ("Y".equalsIgnoreCase(getter.getString())) {
                            return new Boolean (true);
                 } else if ("N".equalsIgnoreCase(getter.getString())) {
                            return new Boolean (false);
                 } else {
                            throw new SQLException();
                 }
        }
        public void setParameter(ParameterSetter setter, Object parameter)
        throws SQLException {
                 if (((Boolean)parameter).booleanValue()) setter.setString("Y");
                 else setter.setString("N");
        }
        public Object valueOf(String s) {
                 return new Boolean ("Y".equalsIgnoreCase(s));
        }
}
Custom Type Handlers

<resultMap id="myClass" class="my.package.MyClass">
   ...
   <result property="foo" column="bar"
   typeHandler="some.package.YesNoBoolTypeHandler"/>
   ...
</resultMap>




<insert id="myQuery" resultMap="myClass"
parameterClass="my.package.MyClass">
         INSERT INTO table1 SET bar =
         #foo,handler=some.package.YesNoBoolTypeHandler#
</insert>
Paging / Selecting a Range
selectKey

<insert id="addForumThread" parameterClass="java.util.HashMap">
   INSERT INTO forum_threads SET
   forum_id = #forumID#,
   title = #title#,
   created_time = #createdTime#,
   last_updated_time = #createdTime#,
   <selectKey resultClass="int">
       SELECT MAX(id) FROM forum_threads
   </selectKey>
</insert>
Caching Features
<cacheModel id="fooCache" type="{LRU|MEMORY|FIFO|OSCACHE}"
readOnly="{true|false}" serialize="{true|false}">
      <flushInterval hours="24"/>
      <flushOnExecute statement="insertFoo"/>
      <flushOnExecute statement="updateFoo"/>
      <flushOnExecute statement="deleteFoo"/>
      <property name="size" value="1000"/>
</cacheModel>


<select id="getFoo" cacheModel="fooCache">
         SELECT * FROM bar WHERE id = #value#
</select>


<insert id="insertFoo">
         INSERT INTO bar SET ...
</insert>
...
Transactions
public updateItemDescription(String itemId, String newDescription)
throws SQLException
{
       try
       {
               sqlMap.startTransaction();

                 Item item = (Item)
                        sqlMap.queryForObject("getItem", itemId);

                 item.setDescription (newDescription);

                 sqlMap.update("updateItem", item);

                 sqlMap.commitTransaction();
       }
       finally
       {

                 sqlMap.endTransaction();
       }
}
What About Hibernate?

            iBATIS                                    Hibernate
• Separation of code and SQL                • SQL alongside code

• Simpler configuration and setup*

• Total control over SQL queries            • Cross-DB query language (HQL)

• Shallow learning curve                    • ???

• Handles application complexities          • Works very well when data model
better**                                    closely resembles object model**



          **No Fluff Just Stuff's Mark Richards' two cents:
          http://www.nofluffjuststuff.com/media.jsp?mediaId=27


             *Source: http://www.devx.com/Java/Article/31481/0/page/1
Who is Using iBatis?

                       • CNet.com

                       • MySpace.com

                       • OfficeMax.com

                       • JPMorganChase.com

                       • 1up.com

                       • PowerSentry.com

                       (and more)


     Source: http://www.ociweb.com/mark/programming/iBATIS.html#WhoUses
Now What?


       http://ibatis.apache.org

iBATIS

  • 1.
    Omaha Java UsersGroup March 18, 2008 Corey A. Spitzer
  • 2.
    The Context • J2EE (with Spring) • OOP • SQL Relational Database
  • 3.
    What is iBATIS? ObjectOriented Object Logic / DAO iBATIS Database Code Query Relational
  • 4.
    A More DetailedLook calls Code SqlMapClient insert() loads update() calls delete() query() SQL Maps javax.sql.DataSource Queries Result Maps Magic Magic Database
  • 5.
    The SQL MapAnatomy Code calls SqlMapClient loads calls SQL Maps DataSource <sqlMap namespace="myNamespace"> Magic Magic <resultMap id="myClass" class="full.package.MyClass"> Database <result property="foo" column="col1"/> <result property="bar" column="col2"/> ... </resultMap> ... <!-- ===================================================== --> <sql id="myQuery" resultMap="myClass"> SELECT col1, col2 FROM table1 </sql> ... </sqlMap>
  • 6.
    The Code Anatomy Code calls SqlMapClient loads calls import java.sql.SQLException; SQL Maps DataSource import com.ibatis.sqlmap.client.SqlMapClient; ... Magic Magic public class MyDAO Database { private SqlMapClient myDB; public void frobnicate(MyObject someObject) throws SQLException { List<MyClass> list = myDB.queryForList("myQuery"); Foo myFoo = (Foo)myDB.queryForObject("getFooByID", 1337); myDB.update("myQuery3"); myDB.insert("myQuery4", someObject); ... } ... }
  • 7.
    Any Questions sofar? calls Code SqlMapClient insert() loads update() calls delete() query() SQL Maps javax.sql.DataSource Queries Result Maps Magic Magic Database
  • 8.
    Implicit Mapping <sqlMap namespace="myNamespace"> <resultMap id="myClass" class="full.package.Class"> <result property="foo" column="col1"/> <result property="bar" column="col2"/> ... </resultMap> ... <!-- ===================================================== --> <sql id="myQuery" resultClass="full.package.Class"> SELECT col1 as foo, col2 as bar FROM table1 </sql> ... </sqlMap>
  • 9.
    Inheritance Object Oriented Code Relational Database Fruit fruits id - int id - mediumint(7), PK dateBought - long date_bought - int(11) type - enum('a', 'o') apples Apple Orange fruit_id - mediumint(7), FK worm_count - decimal(4,1) wormCount - float bioengineered - boolean oranges fruit_id - mediumint(7), FK bioengineered - bool
  • 10.
    Complex Members Object Oriented Code Relational Database Cake cakes id - int id - mediumint(7), PK flavor - String flavor - enum('chocolate', ...) toppings - List<CakeTopping> cakes_to_toppings cake_id - mediumint(7), FK topping_id - mediumint(7), FK CakeTopping id - int name - String cake_toppings containsHFCS - boolean id - mediumint(7), PK name - varchar(20) contains_hfcs - bool
  • 11.
  • 12.
    Custom Type Handlers publicclass YesNoBoolTypeHandler implements TypeHandlerCallback { public Object getResult(ResultGetter getter) throws SQLException { if ("Y".equalsIgnoreCase(getter.getString())) { return new Boolean (true); } else if ("N".equalsIgnoreCase(getter.getString())) { return new Boolean (false); } else { throw new SQLException(); } } public void setParameter(ParameterSetter setter, Object parameter) throws SQLException { if (((Boolean)parameter).booleanValue()) setter.setString("Y"); else setter.setString("N"); } public Object valueOf(String s) { return new Boolean ("Y".equalsIgnoreCase(s)); } }
  • 13.
    Custom Type Handlers <resultMapid="myClass" class="my.package.MyClass"> ... <result property="foo" column="bar" typeHandler="some.package.YesNoBoolTypeHandler"/> ... </resultMap> <insert id="myQuery" resultMap="myClass" parameterClass="my.package.MyClass"> INSERT INTO table1 SET bar = #foo,handler=some.package.YesNoBoolTypeHandler# </insert>
  • 14.
  • 15.
    selectKey <insert id="addForumThread" parameterClass="java.util.HashMap"> INSERT INTO forum_threads SET forum_id = #forumID#, title = #title#, created_time = #createdTime#, last_updated_time = #createdTime#, <selectKey resultClass="int"> SELECT MAX(id) FROM forum_threads </selectKey> </insert>
  • 16.
    Caching Features <cacheModel id="fooCache"type="{LRU|MEMORY|FIFO|OSCACHE}" readOnly="{true|false}" serialize="{true|false}"> <flushInterval hours="24"/> <flushOnExecute statement="insertFoo"/> <flushOnExecute statement="updateFoo"/> <flushOnExecute statement="deleteFoo"/> <property name="size" value="1000"/> </cacheModel> <select id="getFoo" cacheModel="fooCache"> SELECT * FROM bar WHERE id = #value# </select> <insert id="insertFoo"> INSERT INTO bar SET ... </insert> ...
  • 17.
    Transactions public updateItemDescription(String itemId,String newDescription) throws SQLException { try { sqlMap.startTransaction(); Item item = (Item) sqlMap.queryForObject("getItem", itemId); item.setDescription (newDescription); sqlMap.update("updateItem", item); sqlMap.commitTransaction(); } finally { sqlMap.endTransaction(); } }
  • 18.
    What About Hibernate? iBATIS Hibernate • Separation of code and SQL • SQL alongside code • Simpler configuration and setup* • Total control over SQL queries • Cross-DB query language (HQL) • Shallow learning curve • ??? • Handles application complexities • Works very well when data model better** closely resembles object model** **No Fluff Just Stuff's Mark Richards' two cents: http://www.nofluffjuststuff.com/media.jsp?mediaId=27 *Source: http://www.devx.com/Java/Article/31481/0/page/1
  • 19.
    Who is UsingiBatis? • CNet.com • MySpace.com • OfficeMax.com • JPMorganChase.com • 1up.com • PowerSentry.com (and more) Source: http://www.ociweb.com/mark/programming/iBATIS.html#WhoUses
  • 20.
    Now What? http://ibatis.apache.org