Spring MVC MyBatis Integration Tutorial

Last few months, I'm working at a project with Spring MVC and Hibernate. Now, I want to try MyBatis. In this article, I'll tell you how to useMyBatis with Spring MVC.

According to WikiPedia, database transaction should provide an “all-or-nothing” proposition, stating that each work-unit performed in a database must either complete in its entirety or have no effect whatsoever. Further, the system must isolate each transaction from other transactions, results must conform to existing constraints in the database, and transactions that complete successfully must get written to durable storage.

So on this example, im trying to create a simple MyBatis database transaction, managed by Spring Framework. Okay, so this is my pom file, as you can see, im using Spring version 4.1.5.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.trunkshell</groupId>
    <artifactId>voj</artifactId>
    <packaging>war</packaging>
    <version>1.0.0-SNAPSHOT</version>
    <name>Verwandlung Online Judge</name>
    <url>http://maven.apache.org</url>
    <properties>
        <spring.version>4.1.5.RELEASE</spring.version>
        <aspectj.version>1.8.5</aspectj.version>
        <mybatis.version>3.2.8</mybatis.version>
        <druid.version>1.0.13</druid.version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
        <!-- Others -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>voj</finalName>
    </build>
</project>

As you see, I chose Druid as database connection pool. Druid is developed by Alibaba and provides powerful monitoring and extended functionality. Generally, you can also chose dbcp.

Setup web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="verwandlung" version="2.5">
    <display-name>Verwandlung Online Judge</display-name>
    
    <!-- Spring MVC Configuration -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Druid -->
    <servlet>
        <servlet-name>DruidStatView</servlet-name>
        <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DruidStatView</servlet-name>
        <url-pattern>/druid/*</url-pattern>
    </servlet-mapping>
    
    <!-- Home Page -->
    <welcome-file-list>
        <welcome-file>/</welcome-file>
    </welcome-file-list>
</web-app>

Setup Spring Configuration

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <!-- Base Components -->
    <context:annotation-config />
    <context:component-scan base-package="com.trunkshell.voj" />

    <!-- Enable @Controller annotation support -->
    <mvc:annotation-driven />
    <mvc:resources mapping="/assets/**" location="/assets/" />
    <mvc:resources mapping="/druid/**" location="/WEB-INF/support/http/resources" />

    <!-- Map simple view name such as "test" into /WEB-INF/test.jsp -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <!-- JDBC Data Source. It is assumed you have MySQL running on localhost 
        port 3306 with username root and blank password. Change below if it's not 
        the case -->
    <bean id="dataSource" 
        class="com.alibaba.druid.pool.DruidDataSource"
        init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="initialSize" value="${jdbc.initialSize}" />
        <property name="maxActive" value="${jdbc.maxActive}" />
        <property name="minIdle" value="${jdbc.minIdle}" />
        <property name="maxIdle" value="${jdbc.maxIdle}" />
        <property name="maxWait" value="${jdbc.maxWait}" />
        <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
        <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
        <property name="removeAbandoned" value="${jdbc.removeAbandoned}" />
        <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}" />
        <property name="validationQuery" value="SELECT 1" />
    </bean>
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.trunkshell.voj.mapper" />
    </bean>
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

The Structure of Database and Project

The Structure of Database

Suppose we have a database with only one schema:

CREATE TABLE IF NOT EXISTS `voj_users` (
`uid` bigint(20) NOT NULL,
  `username` varchar(16) NOT NULL,
  `password` varchar(32) NOT NULL,
  `email` varchar(64) NOT NULL,
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

The Structure of Project

As the figure shows below, there're 4 main package for this project: controller, service, mapper, and model.
Spring MVC MyBatis Integration Tutorial

Create Model Class

package com.trunkshell.voj.model;

import java.io.Serializable;

public class User implements Serializable {    
    private long uid;
    
    private String username;

    private String password;

    private String email;
    
    private static final long serialVersionUID = 2264535351943252507L;

    // getters and setters
}

Create Mapper Interface

package com.trunkshell.voj.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.trunkshell.voj.model.User;

/**
 * User Data Access Object.
 * @author Xie Haozhe
 */
public interface UserMapper {
    @Select("SELECT * FROM voj_users WHERE uid = #{uid}")
    public User getUserUsingUid(@Param("uid") long uid);
    
    @Select("SELECT * FROM voj_users WHERE username = #{username}")
    public User getUserUsingUsername(@Param("username") String username);
}

Create Service Class

package com.trunkshell.voj.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.trunkshell.voj.mapper.UserMapper;
import com.trunkshell.voj.model.User;

@Service
@Transactional
public class UserService {
    public User getUserUsingUid(long uid) {
        return userMapper.getUserUsingUid(uid);
    }
    
    @Autowired
    private UserMapper userMapper;
}

Use Service in Controller

package com.trunkshell.voj.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = "/")
public class DefaultController {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView indexView(HttpServletRequest request) {
        ModelAndView view = new ModelAndView("index");
        view.addObject("user", userService.getUserUsingUid(1));
        return view;
    }

    @Autowired
    private UserService userService;
}

Launch the Web Application

After you create the classes mentioned above, you can deploy this application. When you visit the homepage(eg: http://localhost:8080/voj), you'll get the user object with UID 1 in JSP pages.

Good luck!

Reference

  • http://edwin.baculsoft.com/2015/01/a-simple-spring-4-and-mybatis-transaction-example/
  • http://blog.csdn.net/dyllove98/article/details/8586310
  • http://www.javacodegeeks.com/2014/02/building-java-web-application-using-mybatis-with-spring.html
  • http://hmkcode.com/mybatis-spring-xml-annotation-mapper/
Contact Us
  • Room 614, Zonghe Building, Harbin Institute of Technology
  • cshzxie [at] gmail.com