iBATIS, Hibernate, and JPA: Which is right for you?

Object-relational mapping solutions compared

1 2 3 4 5 6 7 Page 3
Page 3 of 7

SQLMap.xml

The other XML file is SQLMap.xml, which is in practice named after the table to which it relates. There can be any number of such files in a single application. This file is the place where domain objects are mapped to SQL statements. This descriptor uses parameter maps to map the inputs to the statements and the result maps for mapping SQL ResultSets. This file also contains the queries. Therefore, to change the queries, you need to change the XML, not your application's Java code. The mapping is done by using the actual SQL statements that will interact with the database. Thus, using SQL provides greater flexibility to the developer and makes iBATIS easy to understand to anyone with SQL programming experience.

The SQLMap.xml file that defines the SQL statements to perform CRUD operations on the EMPLOYEE table is shown in Listing 2.

Listing 2. SQLMap.xml for operations on EMPLOYEE

<sqlMap namespace="Employee">
  <typeAlias alias="Employee" type="com.sample.Employee"/>
  <resultMap id="EmpResult" class="Employee">
    <result property="id" column="emp_id"/>
    <result property="firstName" column="emp_firstname"/>
    <result property="lastName" column="emp_lastname"/>
   </resultMap>
  <!-- Select all data from the table using the result map for Employee class.-->
  <select id="selectAllEmps" resultMap="EmpResult">
    select * from EMPLOYEE
  </select>
<!-- Select the data from the table based on the id. -->
<select id="selectEmpById" parameterClass="int" resultClass="Employee">
 <select emp_id as id,emp_firstname as firstName,     emp_lastname as lastName from EMPLOYEE where emp_id= #id#
</select>
<!--  insert the data into the table -->
<insert id="insertEmp" parameterClass="Employee">
    insert into EMPLOYEE (
      emp_id,
       emp_firstname,
       emp_lastname)
    values (
      #id#, #firstName# , #lastName# )
  </insert>
<!-- update the Employee record based on the id -->
  <update id="updateEmp" parameterClass="Employee">
    update EMPLOYEE set
      emp_firstname = #firstName#,
      emp_lastname = #lastName#
    where
      emp_id = #id#
  </update>
<!-- delete the Employee record based on the given id -->
    <delete id="deleteEmp" parameterClass="int">
    delete from EMPLOYEE where emp_id = #id#
  </delete>
</sqlMap>

In Listing 2, the typeAlias tag is used to represent type aliases, so you can avoid typing the full class name every time it would otherwise appear. It contains the resultMap tag, which describes the mapping between the columns returned from a query and the properties of the class represented by the Employee class. The resultMap is optional and it isn't required if the columns in the table (or aliases) match the properties of the class exactly. This resultMap tag is followed by a series of queries. SQLMap.xml can contain any number of queries. All the select, insert, update, and delete statements are written within their respective tags. Every statement is named using the id attribute.

The output from a select query can be mapped to a resultMap or to a result class that is a JavaBean. The aliases in the queries should match the properties of the target result class (that is, the JavaBean). The parameterClass attribute is used to specify the JavaBean whose properties are the inputs. Any parameters in the hash symbol are the properties of the JavaBean.

Loading the descriptor files to your Java application

After you have completed the entire configuration and mapped in both the XML files, SQLMapConfig.xml needs to be loaded by the Java application. The first step is to load the SQLMap.xml configuration file that was created earlier. To do this, you would use the com.ibatis.common.resources.Resources class, which is included with the iBATIS framework, as shown in Listing 3.

Listing 3. Loading SQLMap.xml

private static SqlMapClient sqlMapper;
...
 try {
      Reader reader = Resources.getResourceAsReader("com/mydomain/data/SqlMapConfig.xml");
      sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
      reader.close();
    } catch (IOException e) {
      // Fail fast.
      throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
    }
  }


The SqlMapClient class is used for working with SQLMaps. It allows you to run mapped statements like select, insert, update, and so on. The SqlMapClient object is thread safe; hence, one object is enough. This makes it a good candidate to be a static member. This object is created by reading a single SQLMapConfig.xml file. The iBATIS framework provides the Resources.getResourceAsReader() utility, with which you can read the SQLMapConfig.xml file. Thus, by using this instance of the SQLMap, you can access an object from the database -- in this case, an Employee object.

To invoke the operations on the EMPLOYEE table, different methods are provided on the SQLMap, such as queryForList(), queryForObject(), insert(), update(), and queryForMap(), among others. The queryForList() method, shown in Listing 4, returns a list of Employee objects.

Listing 4. queryForList()

sqlMapper.queryForList("selectAllEmps");

Similarly, you would use the queryForObject() method when only one row was returned as a result of the query. Both methods take the statement name as the parameter.

Corresponding methods are available for performing insert, update, and delete operations, as shown in Listing 5. These methods take both the statement name declared in the SQLMap.xml file and the Employee object as the input.

Listing 5. Insert, update, and delete operations

sqlMapper.insert("insertEmp", emp);
sqlMapper.update("updateEmp", emp);
sqlMapper.delete("deleteEmp", id);

In this way, Java objects are persisted using straight SQL statements in iBATIS.

When to use iBATIS

iBATIS is best used when you need complete control of the SQL. It is also useful when the SQL queries need to be fine-tuned. iBATIS should not be used when you have full control over both the application and the database design, because in such cases the application could be modified to suit the database, or vice versa. In such situations, you could build a fully object-relational application, and other ORM tools are preferable. As iBATIS is more SQL-centric, it is generally referred to as inverted -- fully ORM tools generate SQL, whereas iBATIS uses SQL directly. iBATIS is also inappropriate for non-relational databases, because such databases do not support transactions and other key features that iBATIS uses.

1 2 3 4 5 6 7 Page 3
Page 3 of 7