Thursday, July 12, 2012


MyBatis3 Spring3 integration using Mybatis3 new features

September 17, 2010

The previous post showed how to configure a Mybatis3 Spring3 integration using a configuration style resembling the mybatis 2 usage. This post shows hwo to get started from scratch and building a simple Spring application that uses Mybatis 3.
The simple application tries to edit data in a database table called users:
1create table users(
2id number not null,
3username varchar2(50) not null,
4hashed_password varchar2(70) not null,
5description varchar2(100),
6constraint users_pk primary key(id)
7);
8
9create sequence users_seq nocycle;

The Spring application needs a context file containing the various beans needed for running the application.
In the application context there is a bean for:
  • Data source: for managing database connection
  • Transaction manager: for managing trnasactions
  • Mybatis configuration bean: telles the context where the mybatis files are located
  • UserDao : implements the dao using the mybatis API
  • Manager: the bean that is exposed to the front end layer for performing database operations
  • plus some other configuration for declarative transaction management
The “key beans” are the mybatis config one and the UserDao one. In mybatis 3 there is a new way for invoking the API, i.e. through mapper interfaces; you must write an interface and Mybatis provides an implementation bound to you xml mapper file. Let see how UserDao is implemented:
01package org.jpadbf.spring3mybatis3.dao;
02
03import java.util.List;
04
05import org.apache.ibatis.annotations.Delete;
06import org.apache.ibatis.annotations.Select;
07import org.jpadbf.spring3mybatis3.domain.User;
08
09/**
10 *
11 * @author Giovanni Cuccu
12 *
13 *
14 */
15
16public interface UserDao {
17    public void insert(User user);
18
19    public void update(User user);
20
21    public User loadById(long id);
22
23    @Select("select * from users")
24    public List loadAll();
25
26    @Delete("delete from users where id=#{id}")
27    public void delete(long id);
28}

The UserDao interface specifies the operations needed to run the application. In this example you can note a new mybatis 3 feature: you can specify the sql directly in the code using an annotation. Both the mapper and annotation usage are described in the mybatis 3 manual.
When the application runs mybatis provides a UserDao implementation; the operations can be specified in a xml mapper file or through annotations. UserDao shows that you can mix the two approaches. The operations not annotated will be searched in mybatis 3 xml mapper files.
Here is UserDao.xml:
01xml version="1.0" encoding="UTF-8"?>
02
17
18
19    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21<mapper namespace="org.jpadbf.spring3mybatis3.dao.UserDao">
22
23    <insert id="insert" parameterType="User">
24        <selectKey keyProperty="id" resultType="long" order="BEFORE">
25            select users_seq.nextval as id from dual
26        selectKey>
27        insert into users(id,username,hashed_password,description)
28        values (#{id}, #{username}, #{hashedPassword}, #{description,jdbcType=VARCHAR})
29    insert>
30
31    <update id="update" parameterType="User">
32        update users username=#{username}, hashed_password=#{hashedPassword}, description=#{description}
33        where id=#{id}
34    update>
35
36    <select id="loadById" resultType="User" parameterType="long">
37        select id, username, hashed_password as hashedPassword, description from users where id=#{id}
38    select>
39
40mapper>

The namespace corresponds to the full interface name and the interface methods correspond to the statements (i.e. select,update, etc) id.
Now that we’ve seen the mybatis3 configuration and the UserDao interface it’s time to put them in the Spring application context.
Here is the full application context content:
01xml version="1.0" encoding="UTF-8"?>
03       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
04       xmlns:aop="http://www.springframework.org/schema/aop"
05       xmlns:tx="http://www.springframework.org/schema/tx"
06       xsi:schemaLocation="
11
12    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
13        <property name="location">
14            <value>spring3mybatis3.propertiesvalue>
15        property>
16    bean>
17
18    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
19        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
20        <property name="url" value="jdbc:oracle:thin:@${database.url}"/>
21        <property name="username" value="${database.username}"/>
22        <property name="password" value="${database.password}"/>
23        <property name="validationQuery" value="SELECT 1 FROM DUAL" />
24        <property name="testWhileIdle" value="true" />
25        <property name="timeBetweenEvictionRunsMillis" value="300000" />
26        <property name="numTestsPerEvictionRun" value="6" />
27        <property name="minEvictableIdleTimeMillis" value="1800000" />
28        <property name="initialSize" value="1" />
29        <property name="maxActive" value="5" />
30        <property name="maxIdle" value="5" />
31        <property name="maxWait" value="5000" />
32        <property name="poolPreparedStatements" value="true" />
33        <property name="maxOpenPreparedStatements" value="10" />
34    bean>
35
36    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
37        <property name="dataSource" ref="dataSource"/>
38    bean>
39
40    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
41        <property name="dataSource" ref="dataSource" />
42        <property name="configLocation" value="mybatis-config.xml"/>
43    bean>
44
45    <bean id="userDao" class="org.mybatis.spring.MapperFactoryBean">
46        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
47        <property name="mapperInterface" value="org.jpadbf.spring3mybatis3.dao.UserDao" />
48    bean>
49
50    <bean id="manager" class="org.jpadbf.spring3mybatis3.logic.SimpleManager">
51        <property name="userDao" ref="userDao" />
52    bean>
53
54    <aop:config>
55        <aop:advisor pointcut="execution(* *..SimpleManager.*(..))" advice-ref="simpleTxAdvice" />
56    aop:config>
57
58    <tx:advice id="simpleTxAdvice">
59        <tx:attributes>
60            <tx:method name="insert*"/>
61            <tx:method name="update*"/>
62            <tx:method name="create*"/>
63            <tx:method name="delete*"/>
64            <tx:method name="*" read-only="true"/>
65        tx:attributes>
66    tx:advice>
67
68beans>
The sqlSessionFactory bean is the bean that provides the mybatis configuration, it points to the mybatis main file where you can find aliases and mappers definitions.
The userDao bean is the bean that using the mybatis configuration bean provides the dao implementation; it’s worth noting that the class that defines the bean is a mybatis one and it takes the application interface definition as a parameter.
With this configuration the manager that exposes the Dao operations to the front end layer is the following one:
01 package org.jpadbf.spring3mybatis3.logic;
02
03 import java.util.List;
04
05 import org.jpadbf.spring3mybatis3.dao.UserDao;
06 import org.jpadbf.spring3mybatis3.domain.User;
07
08 public class SimpleManager {
09    private UserDao userDao;
10
11    public void deleteUser(long id) {
12        userDao.delete(id);
13    }
14 
15    public void insertUser(User user) {
16        userDao.insert(user);
17    }
18 
19    public List loadAllUsers() {
20        return userDao.loadAll();
21    }
22 
23    public User loadUserById(long id) {
24        return userDao.loadById(id);
25    }
26 
27    public void updateUser(User user) {
28        userDao.update(user);
29    }
30
31    public UserDao getUserDao() {
32        return userDao;
33    }
34
35    public void setUserDao(UserDao userDao) {
36        this.userDao = userDao;
37    }
38 }

As you can see it simply delegates the operation to the interface witohut any direct link to mybatis api.
Here is a spring3-mybatis3 zip file containing all the configuration and source files need to run the example explained in this post.