Skip to Content »

Tech Life of Recht » Spring iBatis integration with TypeHandlers

 Spring iBatis integration with TypeHandlers

  • May 7th, 2009
  • 8:24 am

I recently had to do some iBatis SqlMap integration in a Spring project. It turned out not to be relevant after all, but I thought I'd share it in case anybody else could use it.
Basically, the problem was that I had to do some type conversion in code. For this, iBatis has the TypeHandler concept, where a handler can be registered on a specific Java type, and when this type is encountered in a SqlMap, the handler is called. Usually, the handlers are configured in the main SqlMap config file by referring to the class name in XML. However, in my case, the handlers had to be Spring-managed beans (they needed some beans to be injected), so the static configuration didn't work. The solution was to extend the SqlMapClientFactoryBean class to do some extra wiring:

CODE:
  1. public class SqlMapTemplateFactoryBean extends SqlMapClientFactoryBean {
  2.  
  3.   private Map<String,TypeHandlerCallback> handlers;
  4.  
  5.   @SuppressWarnings("deprecation")
  6.   @Override
  7.   public Object getObject() {
  8.     ExtendedSqlMapClient client = (ExtendedSqlMapClient) super.getObject();
  9.     if (handlers != null) {
  10.       for (Iterator<?> i = client.getDelegate().getResultMapNames(); i.hasNext(); ) {
  11.         String name = (String) i.next();
  12.         ResultMap map = client.getDelegate().getResultMap(name);
  13.        
  14.         for (ResultMapping rm : map.getResultMappings()) {
  15.           if (rm.getJavaType() != null &&
  16.             handlers.containsKey(rm.getJavaType().getName())) {
  17.             rm.setTypeHandler(new CustomTypeHandler(handlers.get(rm.getJavaType().getName())));
  18.           }
  19.         }
  20.       }
  21.     }
  22.     return client;
  23.   }
  24.  
  25.   @Override
  26.   public Class<SqlMapClientTemplate> getObjectType() {
  27.     return SqlMapClientTemplate.class;
  28.   }
  29.  
  30.   public void setTypeHandlers(Map<String, TypeHandlerCallback> handlers) {
  31.     this.handlers = handlers;
  32.   }
  33. }

This FactoryBean can then be used as a replacement for the regular SqlMapClientFactoryBean, and by setting the typeHandlers property, TypeHander instances can be injected:

CODE:
  1. <bean id="sqlmap" class="dk.test.SqlMapTemplateFactoryBean">
  2.     <property name="dataSource" ref="dataSource" />
  3.     <property name="configLocation" value="classpath:sqlmap.xml" />
  4.     <property name="typeHandlers">
  5.       <map>
  6.         <entry>
  7.           <key><value>dk.test.SomeVO</value></key>
  8.           <bean class="dk.test.SomeTypeHandler">
  9.             <property name="dao" ref="someDAO" />
  10.           </bean>
  11.         </entry>
  12.       </map>
  13.     </property> 
  14.   </bean>

Want your say?

* Required fields. Your e-mail address will not be published on this site

You can use the following XHTML tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>