Hibernate::
beyond "hello world"

 


Download sources

Contact us::


Hibernate and iBatis working together

Last update: Jan-05-2006

Sometimes we need to use SQL heavily to optimize DB access. We have multiple options for that:

  1. Use Hibernate's support for native SQL;
  2. Get JDBC Connection from session and write plain JDBC code;
  3. or we can employ iBatis to help us with JDBC code and mappings;

Why yet another framework? - Because it is good at what it does: optimizing mundane and error prone JDBC code.

Why Hibernate support for SQL is not enough? - In many cases it is enough, but sometimes iBatis mappings are simpler. In the future Hiberante might improve support for native SQL and then there will be less reasons to use any complementary solutions.

For now it might make sense to use iBatis in places where we would like to use JDBC. Benefits:
- SQL is concentrated in well defined places and available for review by DBA and other responsible persons - no more hardcoded SQL.
- iBatis can do mapping for us from JDBC result sets to application objects or simply bring back list of maps for greater flexibility.

The simplest way is to configure them separately and work with them as every framework suggests, but it might be not quite optimal because we would have actions performed in different transactions, which might be undesirable.

The next simple solution would be to let those frameworks operate on the same JDBC connection and manage transactions on JDBC connection level. This solution can be really simple if we will use AOP like techniques and let runtime proxies take care of plumbing code. Let's demonstrate how this can be done with Spring framework AOP capabilities. We will create a simple interceptor (Around advice ) that will provide necessary environment for our code to work within. In simple words that interceptor will initialize thread local variables with necessary Hibernate and iBatis sessions.

AOP proxy

Therefore our code can simply use those sessions how we see fit and that around advice will take care of proper session finalization (read more about such technique here).

TwoORMTest.java

19   
20     public void runIBatisQueryAndGetObjectsViaHibernate() throws SQLException {
21       List list = CallContext.getSqlMapClient().queryForList("summary", null);
22       for (Iterator j = list.iterator(); j.hasNext();) {
23         Object o = j.next();
24         System.out.println("o = " + o + "|" + o.getClass());
25         Map map = ((Map) o);
26         System.out.println("o.total = " +map.get("total") );
27         Object ho = CallContext.getSession().get( VeryComplexDataClass.class, (Serializable) map.get( "id") );
28         System.out.println("ho = " + ho );
29         System.out.println("ho.getDependents() = " + ((VeryComplexDataClass)ho).getDependents());
30       }
31     }

As we can see at line #21 we use iBatis session to get list of rows, and then at row #27 we use Hibernate session to load entire object. If we take a glance at iBatis mapping file we could see that getting the same information without SQL with Hibernate (or any ORM solution for that matter) would be possible, but much much less performant. Hibernate SQL support allows us to do almost the same thing, just slightly less conveniently. iBatis mapping looks as following:

sqlmap-mapping.xml

1    <?xml version="1.0" encoding="UTF-8" ?>
2    
3    <!DOCTYPE sqlMap
4        PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
5        "http://www.ibatis.com/dtd/sql-map-2.dtd">
6    
7    <sqlMap namespace="summary">
8    
9    
10     <select id="summary" resultClass="java.util.HashMap">
11       select M.id, M.name, sum( C.subtot) as total
12       from hpib_objects M, hpib_dep_objects C
13       where m.id = C.ref_obj_id
14       group by M.id, M.name
15     </select>
16   
17   </sqlMap>