Showing posts with label iBatis. Show all posts
Showing posts with label iBatis. Show all posts

Saturday, 23 April 2016

What is iBatis and what are its features and advantages ?


What is iBatis ?
iBATIS is a persistence framework which automates the mapping between SQL databases and objects.
The mappings are decoupled from the application logic by packaging the SQL statements in XML configuration files.
iBATIS is a lightweight framework and persistence API good for persisting POJOs.


How iBatis is different ?
iBATIS emphasizes use of SQL, while other frameworks typically use a custom query language such has the Hibernate Query Language (HQL) or Enterprise JavaBeans Query Language (EJB QL)


Features
Simplicity - one of the simplest persistence frameworks
Fast Development - facilitate hyper-fast development
Portability - possible to implement for many languages / platforms like Java, Ruby, and C# for Microsoft .NET
Independent Interfaces - Database-independent interfaces and APIs
Open source - Free and Open source


Advantages of iBATIS
Suppports Stored procedures
encapsulates SQL in the form of stored procedures so that business logic is kept out of the database, and the application is easier to deploy and test, and is more portable.

Supports Inline SQL
No pre-compiler is needed, and you have full access to all of the features of SQL.

Supports Dynamic SQL
provides features for dynamically building SQL queries based on parameters.

Supports ORM
supports many of the features as other ORM tool (lazy loading, join fetching, caching, runtime code generation and inheritance)

What is iBatis configuratin file ?


Create an XML configuration file with name SqlMapConfig.xml where you need to provide all configurations required for iBatis.
It is important that the files SqlMapConfig.xml and other mapping files (like, Employee.xml) should be present in the class path.

Basic contents of SqlMapConfig.xml
<sqlMapConfig>
 <settings useStatementNamespaces="true" />
 <transactionManager type="JDBC">
  <dataSource type="SIMPLE">
   <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
   <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost:3306/testdb"/>
   <property name="JDBC.Username" value="root"/>
   <property name="JDBC.Password" value="root"/>
  </dataSource>
  </transactionManager>
 <sqlMap resource="Employee.xml"/>
</sqlMapConfig>


Other properties for SqlMapConfig.xml
<property name="JDBC.AutoCommit" value="true" />
<property name="Pool.MaximumActiveConnections" value="10" />
<property name="Pool.MaximumIdleConnections" value="5" />
<property name="Pool.MaximumCheckoutTime" value="150000" />
<property name="Pool.MaximumTimeToWait" value="500" />
<property name="Pool.PingQuery" value="select 1 from Employee" />
<property name="Pool.PingEnabled" value="false" />

How to perform CRUD operations in iBatis ?


To perform any CRUD ( Create, Write, Update and Delete) operation using iBATIS, you would need to create a POJOs class corresponding to the table. This class describes the objects that will "model" database table rows.

EMPLOYEE table in MySQL
CREATE TABLE EMPLOYEE (
  id INT NOT NULL auto_increment,
  first_name VARCHAR(20) default NULL,
  last_name VARCHAR(20) default NULL,
  salary INT default NULL, PRIMARY KEY (id)
);

Employee POJO Class
We would create Employee class in Employee.java file as follows:
public class Employee {
  private int id;
  private String first_name;
  private String last_name;
  private int salary;
  /* Define constructors for the Employee class. */
  public Employee() {}
  public Employee(String fname, String lname, int salary) {
    this.first_name = fname;
    this.last_name = lname;
    this.salary = salary; }
  }

Employee.xml File
To define SQL mapping statement using iBATIS, we would use insert tag and inside this tag definition we would define an "id" which will be used in IbatisInsert.java file for executing SQL INSERT query on database.
<?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="Employee">
  <insert id="insert" parameterClass="Employee">
    insert into EMPLOYEE(first_name, last_name, salary) values (#first_name#, #last_name#, #salary#)
    <selectKey resultClass = "int" keyProperty="id">
        select last_insert_id() as id
     </selectKey>
  </insert>
  <select id="getAll" resultClass="Employee">
       SELECT * FROM EMPLOYEE
  </select>
  <update id="update" parameterClass="Employee">
      UPDATE EMPLOYEE SET first_name = #first_name# WHERE id = #id#
   </update>
   <delete id="delete" parameterClass="int">
      DELETE FROM EMPLOYEE WHERE id = #id#
   </delete>
</sqlMap>

Here, parameterClass could take a value as string, int, float, double or any class object based on requirement.
In this example we would pass Employee object as a parameter while calling insert method of SqlMap class.
If your database table uses an IDENTITY, AUTO_INCREMENT, or SERIAL column or you have defined a SEQUENCE/GENERATOR, you can use the <selectKey> element in an <insert> statement to use or return that database-generated value.



READ OPERATION
Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(rd);
/* This would read all records from the Employee table. */
System.out.println("Going to read records.....");
List <Employee> ems = (List<Employee>)smc.queryForList("Employee.getAll", null);
Employee em = null;
for (Employee e : ems) {
  System.out.print(" " + e.getId() + " " + e.getFirstName() + " " + e.getLastName() + " " + e.getSalary());
  em = e;
  System.out.println();
}
System.out.println("Records Read Successfully ");


INSERT OPERATION
Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(rd);
/* This would insert one record in Employee table. */
System.out.println("Going to insert record.....");
Employee em = new Employee("Zara", "Ali", 5000);
smc.insert("Employee.insert", em);
System.out.println("Record Inserted Successfully ");
/* Logic to read all records, in order to check record insertion */


DELETE OPERATION
Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(rd);
/* This would delete one record in Employee table. */
System.out.println("Going to delete record.....");
int id = 1;
smc.delete("Employee.delete", id );
System.out.println("Record deleted Successfully ");
/* Logic to read all records, in order to check record deletion */


UPDATE OPERATION
Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(rd);
/* This would update one record in Employee table. */
System.out.println("Going to update record.....");
Employee rec = new Employee();
rec.setId(1);
rec.setFirstName( "Roma");
smc.update("Employee.update", rec );
System.out.println("Record updated Successfully ");
/* Logic to read all records, in order to check record update */

How to use Result Map in iBatis ?


The resultMap element is the most important and powerful in iBATIS.
It can reduce your iBatis code to minimum.

Example
EMPLOYEE table in MySQL
CREATE TABLE EMPLOYEE (
  id INT NOT NULL auto_increment,
  first_name VARCHAR(20) default NULL,
  last_name VARCHAR(20) default NULL,
  salary INT default NULL, PRIMARY KEY (id)
);

Employee POJO Class
public class Employee {
  private int id;
  private String first_name;
  private String last_name;
  private int salary;
  /* Getters and setters */
}


Employee.xml File
<?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="Employee">
  <insert id="insert" parameterClass="Employee">
    insert into EMPLOYEE(first_name, last_name, salary) values (#first_name#, #last_name#, #salary#)
    <selectKey resultClass = "int" keyProperty="id">
        select last_insert_id() as id
     </selectKey>
  </insert>
  <select id="getAll" resultClass="Employee">
       SELECT * FROM EMPLOYEE
  </select>
  <update id="update" parameterClass="Employee">
      UPDATE EMPLOYEE SET first_name = #first_name# WHERE id = #id#
   </update>
   <delete id="delete" parameterClass="int">
      DELETE FROM EMPLOYEE WHERE id = #id#
   </delete>
   <!-- Using ResultMap -->
   <resultMap id="result" class="Employee">
    <result property="id" column="id"/>
    <result property="first_name" column="first_name"/>
    <result property="last_name" column="last_name"/>
    <result property="salary" column="salary"/>
   </resultMap>
   <select id="useResultMap" resultMap="result">
       SELECT * FROM EMPLOYEE WHERE id=#id#
    </select>
</sqlMap>


Java code to use Result Map
Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(rd);
int id = 1;
System.out.println("Going to read record.....");
Employee e = (Employee) smc.queryForObject ("Employee.useResultMap", id);
System.out.println("ID: " + e.getId());
System.out.println("First Name: " + e.getFirstName());
System.out.println("Last Name: " + e.getLastName());
System.out.println("Salary: " + e.getSalary());
System.out.println("Record read Successfully ");