Last few months, I’m working on 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 transactions should provide an “all-or-nothing” proposition, stating that each work-unit performed in a database must either be completed 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 in this example, I’m trying to create a simple MyBatis database transaction, managed by Spring Framework. Okay, so this is my pom file, as you can see, I’m 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>org.verwandlung</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 choose Druid as the database connection pool. Druid is developed by Alibaba and provides powerful monitoring and extended functionality. Generally, you can also choose 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="org.verwandlung.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="org.verwandlung.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 the Project

As the figure shows below, there’s 4 main packages for this project: controller, service, mapper, and model.

Create Model Class

package org.verwandlung.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 org.verwandlung.voj.mapper;

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

import org.verwandlung.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 org.verwandlung.voj.service;

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

import org.verwandlung.voj.mapper.UserMapper;
import org.verwandlung.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 org.verwandlung.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

The Disqus comment system is loading ...
If the message does not appear, please check your Disqus configuration.