When we talk about the persistence framework, we think in Hibernate/JPA. Recently I was presented to iBatis, a framework that so easy to install, to configure and to use. You can download it in your sponsor site, Apache, clicking here.

Setting iBatis

Unlike another frameworks, to configure iBatis you need only one XML file, called SqlMapConfig.

The mains sections of XML are:

<properties resource="tuto/ibatis/config/SqlMap.properties"/>

This code is optional and specifies the .properties file that’ll be used to declare variables used in configuration.

<typeAlias alias="car" type="tuto.ibatis.beans.Car"/>

Defines the JavaBean used and your alias. You can set much lines, depending of modeling complexity.
In example, we’ll Car bean below:

public class Car {
	private Long carId;
	private String company;
	private String model;
	private String color;
	private Integer	hp;
	private Float price;

	//Setters and getters omitted
}
<transactionManager type="JDBC">
    <dataSource type="SIMPLE">
        <property name="JDBC.Driver" value="${driver}"/>
        <property name="JDBC.ConnectionURL" value="${url}"/>
        <property name="JDBC.Username" value="${username}"/>
        <property name="JDBC.Password" value="${password}"/>
    </dataSource>
</transactionManager>

Parameters used in database connection. The variables ${driver}, ${url}, ${username} and ${password} are defined in .properties file in section properties. If you prefer, can put the values directly in fields.

See the complete file:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
    <properties resource="tuto/ibatis/config/SqlMap.properties"/>

    <settings
        cacheModelsEnabled="true"
        enhancementEnabled="true"
        lazyLoadingEnabled="true"
        maxRequests="32"
        maxSessions="10"
        maxTransactions="5"
        useStatementNamespaces="false" />

    <typeAlias alias="car" type="tuto.ibatis.beans.Car"/>

    <transactionManager type="JDBC">
        <dataSource type="SIMPLE">
            <property name="JDBC.Driver" value="${driver}"/>
            <property name="JDBC.ConnectionURL" value="${url}"/>
            <property name="JDBC.Username" value="${username}"/>
            <property name="JDBC.Password" value="${password}"/>
        </dataSource>
    </transactionManager>

    <sqlMap resource="tuto/ibatis/sqlmaps/CarSqlMap.xml"/>
</sqlMapConfig>

The properties have this content:

driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@<host>:<porta>:<sid>
username=<login>
password=<senha>

Next you need to configure the SqlMap. This XML contains the querys used in application and your name need be equals described in sqlMap section of SqlMapConfig, in our case will be CarSqlMap.xml

In example only we will see utilization of tags select, insert, update and delete.

<select id="getCars" resultClass="tuto.ibatis.beans.Car"
	parameterClass="java.lang.Long">
    SELECT COMPANY  as company,
           MODEL    as model,
           COLOR    as color,
           HP       as hp,
           PRICE    as price
    FROM TBL_CAR
    WHERE CAR_ID = #var#
</select>

Execute the select statement can return a single object or one collection of objects, the type is same of resultClass attribute, o parameterClass is the type sent to execute the query and the id is the query identification call.

We will use the SqlMap below:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
	"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Car">
    <select id="getCars" resultClass="tuto.ibatis.beans.Car"
    parameterClass="java.lang.Long">
        SELECT COMPANY  as company,
               MODEL    as model,
               COLOR    as color,
               HP       as hp,
               PRICE    as price
        FROM TBL_CAR
        WHERE CAR_ID = #var#
    </select>

    <insert id="addCar" parameterClass="tuto.ibatis.beans.Car">
        INSERT INTO TBL_CAR (CAR_ID, COMPANY, MODEL, COLOR, HP, PRICE)
        VALUES (#carId#, #company#, #model#, #color#, #hp#, #price#)
    </insert>

    <delete id="delCar" parameterClass="java.lang.Long">
        DELETE FROM TBL_CAR WHERE CAR_ID = #var#
    </delete>

    <update id="updCar" parameterClass="tuto.ibatis.beans.Car">
        UPDATE TBL_CAR
          SET COMPANY = #company#,
              MODEL = #model#,
              COLOR = #color#,
              HP = #hp#,
              PRICE = #price#
        WHERE CAR_ID = #carId#
    </update>
</sqlMap>

Data base connection configured, now we will implements the singleton class the will used as SqlMapClient, called OracleMapConfig.

package tuto.ibatis.connection;

import java.io.Reader;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

public class OracleMapConfig {
	private static final SqlMapClient sqlMapClient;

	static{
		try{
			//Defining path of SqlMapConfig and creating reader
			String res = "tuto/ibatis/config/SqlMapConfig.xml";
			Reader reader = Resources.getResourceAsReader(res);

			//Retrieving the client to SqlMap
			sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
		} catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	//Method used to retrieve the client
	public static SqlMapClient getSqlMapClient(){
		return sqlMapClient;
	}
}

The client is responsible for execute the querys configured in SqlMap and return the results.

Executing Querys and treating the return

To call any query is too simple, only execute the correspondent method of client class.

The select can be called this way:

OracleMapConfig.getSqlMapClient().queryForObject("<id>", <parâmetro>);

Theid need be equals of id specified in SqlMap

Only one line is return in code above, to get all lines change to queryForList, this way:

OracleMapConfig.getSqlMapClient().queryForList("<id>", <parâmetro>);

Will be returned a Collection containing the objects;

Select

try{
	Car car = (Car)OracleMapConfig.getSqlMapClient().queryForObject("getCars",
		new Long(readKeyboard()));

	System.out.println("Company: "+car.getCompany());
	System.out.println("Model: "+car.getModel());
	System.out.println("Color: "+car.getColor());
	System.out.println("HP: "+car.getHp());
	System.out.println("Price: "+car.getPrice());
}catch (Exception e) {
	e.printStackTrace();
}

The id “getCars” are defined in select attributes of SqlMap, providing one Long type and retrieving a Car type, both defined in line <select id=”getCars” resultClass=”tuto.ibatis.beans.Car” parameterClass=”java.lang.Long“>.

Insert

try{
	OracleMapConfig.getSqlMapClient().insert("addCar", newCar);
}catch (Exception e) {
	e.printStackTrace();
}

Now we will provide as parameter a Car type, <insert id=”addCar” parameterClass=”tuto.ibatis.beans.Car“>, and call the methods using sharp (#), this way:

INSERT INTO TBL_CAR (CAR_ID, COMPANY, MODEL, COLOR, HP, PRICE)
VALUES (#carId#, #company#, #model#, #color#, #hp#, #price#)

Delete

try{
	int lines = OracleMapConfig.getSqlMapClient().delete("delCar",
		new Long(readKeyboard()));

	System.out.println(lines + " lines deleted");
}catch (Exception e) {
	e.printStackTrace();
}

The method delete of client return a type int, this represents the number of rows deleted.

Update

try{
	int lines = OracleMapConfig.getSqlMapClient().update("updCar", car);

	System.out.println(lines + " cars updated");
}catch (Exception e) {
	e.printStackTrace();
}

Update return a type int, this represents the number of rows affected by update.

How you see, with only three XML and three classes we built a simple storage management and price consulting system.

You can download the source code of this tutorial clicking here.

Until next post!