iBatis: SQL Mapper Framework
When it comes to persistence frameworks in the Java ecosystem, the conversation often gravitates toward full ORM solutions like Hibernate. However, there's a whole category of developers who prefer to keep their SQL close and their control tighter. This is where iBatis (now continued as MyBatis) shines.
In this post, we'll explore what iBatis is, how it differs from traditional ORMs, and how to get started with it.
What Is iBatis?
iBatis is a SQL Mapper framework. Rather than generating SQL for you like a traditional Object-Relational Mapping (ORM) tool, iBatis lets you write your own SQL statements and maps the results to Java objects (and vice versa).
The core philosophy is simple:
You write the SQL. iBatis handles the boilerplate of parameter binding and result mapping.
This gives you the productivity benefits of automated data mapping while retaining full control over your queries.
iBatis vs. Full ORM
Understanding when to use iBatis comes down to understanding the trade-offs:
| Aspect | iBatis (SQL Mapper) | Hibernate (ORM) |
|---|---|---|
| SQL Control | Full — you write it | Generated (mostly) |
| Learning Curve | Gentle | Steeper |
| Complex Queries | Excellent | Can be awkward |
| Caching | Basic | Advanced |
| Legacy DB Support | Excellent | Requires adaptation |
If you're working with a legacy database, stored procedures, or highly optimized queries, iBatis is often the better fit.
Core Components
An iBatis-based application typically involves the following pieces:
- SqlMapConfig.xml — the main configuration file (datasource, transaction manager, and references to mapper files).
- SQL Map XML files — where you define your SQL statements and mappings.
- Domain objects (POJOs) — plain Java classes representing your data.
- SqlMapClient — the runtime API used to execute mapped statements.
Configuration Example
Here's a minimal SqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
<property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/appdb"/>
<property name="JDBC.Username" value="root"/>
<property name="JDBC.Password" value="secret"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/example/maps/User.xml"/>
</sqlMapConfig>
Defining a SQL Map
Let's map a simple User domain object. First, the POJO:
public class User {
private int id;
private String username;
private String email;
// getters and setters omitted for brevity
}
Now the corresponding User.xml map file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="User">
<resultMap id="userResult" class="com.example.User">
<result property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
</resultMap>
<select id="getUserById" parameterClass="int" resultMap="userResult">
SELECT user_id, username, email
FROM users
WHERE user_id = #value#
</select>
<insert id="insertUser" parameterClass="com.example.User">
INSERT INTO users (username, email)
VALUES (#username#, #email#)
</insert>
</sqlMap>
Notice the #value# and #username# placeholders. These are inline parameters that iBatis safely binds using prepared statements, protecting you from SQL injection.
Executing Statements
With the mapping in place, you can execute statements through the SqlMapClient:
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
// Query a single user
User user = (User) sqlMap.queryForObject("getUserById", 1);
// Insert a new user
User newUser = new User();
newUser.setUsername("jdoe");
newUser.setEmail("jdoe@example.com");
sqlMap.insert("insertUser", newUser);
Dynamic SQL
One of iBatis's standout features is dynamic SQL. You can build queries conditionally based on the parameters provided:
xml
<select id="searchUsers" parameterClass="java.util.Map" resultMap="userResult">
SELECT user_id, username, email
FROM users
<dynamic prepend="WHERE">
<isNotNull property="username">
username = #username#
</isNotNull>
<isNotNull property="email" prepend="AND">
email = #email#
</isNotNull>
</dynamic
Top comments (0)