Spring 整合 MyBatis 教程(SSM 整合)

前言

本文主要介绍 Spring + Spring MVC + MyBatis 整合(SSM),开发工具基于 Eclipse + Maven。值得一提的是,下文只给出 SSM 整合所需的最小配置内容,在生产环境需要适当优化项目的配置,尤其是 Log4j2Druid 的配置。完整的项目代码可以直接从 GitHub 下载对应章节 ssm-study

版本说明

名称版本
Spring4.3.2.RELEASE
MyBatis3.4.1
Druid1.0.25
Log4j22.6.2
MySQL5.7.26

官方整合案例

准备工作

数据库初始化

本文的案例代码依赖以下数据库表结构,因此需要提前初始化好数据库才能运行项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
--- 创建数据库
CREATE DATABASE `mybatis_lesson` DEFAULT CHARACTER SET utf8mb4;

--- 创建数据库表
CREATE TABLE `t_employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`dept_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--- 插入表数据
insert into t_employee(id, last_name, gender, email) values(1, 'Jim','1', 'jim@gmail.com');
insert into t_employee(id, last_name, gender, email) values(2, 'Tom','1', 'tom@gmail.com');
insert into t_employee(id, last_name, gender, email) values(3, 'Peter','1', 'peter@gmail.com');

创建 Maven Web 项目

在 Eclipse 内,提前创建好基于 Maven 的 Web 项目。由于篇幅有限,这里不再累述创建步骤,详细教程可看这里

快速开始

引入 Maven 依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<log4j.version>2.6.2</log4j.version>
<mysql.version>5.1.37</mysql.version>
<druid.version>1.0.25</druid.version>
<mybatis.version>3.4.1</mybatis.version>
<mybatis-spring.version>1.3.0</mybatis-spring.version>
<servlet.version>3.1.0</servlet.version>
<spring.version>4.3.2.RELEASE</spring.version>
<gson.version>2.7</gson.version>
<commons-collections.version>3.2.2</commons-collections.version>
</properties>

<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>

<!-- JSTL -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- Log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>

<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>

<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.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>${mybatis-spring.version}</version>
</dependency>

<!-- Spring IOC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring Web -->
<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>

<!-- Spring DAO -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Common Tools -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>

<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections.version}</version>
</dependency>
</dependencies>

创建项目配置文件

Log4j2 配置文件

/src/main/resources 目录下创建 log4j2.xml 配置文件,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

数据库配置文件

/src/main/resources 目录下创建 db.properties 配置文件,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis_lesson?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

jdbc.miniPoolSize=10
jdbc.maxPoolSize=30
jdbc.initialPoolSize=1
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.preferredTestQuery=select 1

MyBatis 配置文件

/src/main/resources 目录下创建 mybatis-config.xml 配置文件,用于存放 MyBatis 的全局核心配置信息,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 开启驼峰命名自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>

</configuration>

Spring 配置文件

Spring MVC 配置文件

/src/main/resources 目录下创建 application-servlet.xml 配置文件,用于配置 Spring MVC 的运行,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- Spring 扫描控制器组件 -->
<context:component-scan base-package="com.clay.mybatis" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<!-- Spring MVC 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>

<!-- Spring MVC 注解驱动 -->
<mvc:annotation-driven></mvc:annotation-driven>

<mvc:default-servlet-handler />

</beans>
Spring Context 配置文件

/src/main/resources 目录下创建 application-context.xml 配置文件,Spring 整合 MyBatis 的核心配置信息就写在里面(也就是定义 SqlSessionFactoryBean 的 Bean),其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- 引入数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties" />

<!-- 扫描组件 -->
<context:component-scan base-package="com.clay.mybatis">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.maxPoolSize}" />
<property name="initialSize" value="${jdbc.initialPoolSize}" />
<property name="maxWait" value="${jdbc.maxWait}" />
<property name="minIdle" value="${jdbc.miniPoolSize}" />
<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${jdbc.preferredTestQuery}" />
<property name="testWhileIdle" value="true" />
<property name="filters" value="stat" />
</bean>

<!-- 事务管理 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启基于注解的事务 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />

<!-- 定义 SqlSessionFactory -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 类型别名 -->
<property name="typeAliasesPackage" value="com.clay.mybatis.bean" />
<!--指定 SQL 映射文件的位置 -->
<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />
<!-- 指定 MyBatis 全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>

<!-- 定义 SqlSessionTemplate -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
</bean>

<!-- 扫描 MyBatis 的 Mapper 接口 -->
<mybatis-spring:scan base-package="com.clay.mybatis.dao" />

<!-- 或者使用以下的配置来扫描 Mapper 接口 -->
<!--
<bean id="configure" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.clay.mybatis.dao"></property>
</bean>
-->

</beans>

更改 web.xml 配置文件

更改 /src/main/webapp/WEB-INF 目录下的 web.xml 的配置文件,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://JAVA.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<!-- Spring 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Spring MVC 配置 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-servlet.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 字符集编码过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

项目核心代码

DAO 层

  • EmployeeMapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.clay.mybatis.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.clay.mybatis.bean.Employee;

@Mapper
public interface EmployeeMapper {

public List<Employee> queryAll();

public boolean delEmpById(Long id);

}

Service 层

  • EmployeeService
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.clay.mybatis.service;

import java.util.List;

import com.clay.mybatis.bean.Employee;

public interface EmployeeService {

public List<Employee> list();

public boolean deleteEmployee(Long id);

}
  • EmployeeServiceImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.clay.mybatis.service.impl;

import java.util.List;

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

import com.clay.mybatis.bean.Employee;
import com.clay.mybatis.dao.EmployeeMapper;
import com.clay.mybatis.service.EmployeeService;

@Service
public class EmployeeServiceImpl implements EmployeeService {

@Autowired
private EmployeeMapper employeeMapper;

@Override
public List<Employee> list() {
return this.employeeMapper.queryAll();
}

@Override
public boolean deleteEmployee(Long id) {
return this.employeeMapper.delEmpById(id);
}

}

Controller 层

  • HomePageController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.clay.mybatis.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomePageController {

@RequestMapping("/")
public String index() {
return "index";
}

@RequestMapping("/index.jsp")
public String indexJsp() {
return "index";
}

@RequestMapping("/index.html")
public String indexHtml() {
return "index";
}

}
  • EmployeeController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.clay.mybatis.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.clay.mybatis.bean.Employee;
import com.clay.mybatis.service.EmployeeService;

@Controller
@RequestMapping("/employee")
public class EmployeeController {

@Autowired
private EmployeeService employeeService;

@RequestMapping("/list")
public ModelAndView list() {
List<Employee> list = this.employeeService.list();
ModelAndView view = new ModelAndView("/employee/list", "employees", list);
return view;
}

@ResponseBody
@RequestMapping("/delete/{id}")
public boolean deleteEmployee(@PathVariable("id") Long id) {
return this.employeeService.deleteEmployee(id);
}

}

JSP 页面代码

提示

根据上面的 web.xml 配置文件,JSP 页面的源文件统一存放在 /src/main/webapp/WEB-INF/pages 目录下。

  • index.jsp
1
2
3
4
5
6
7
8
9
10
11
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>员工列表</title>
</head>
<body>
<a href="/ssm-study/employee/list/">查询所有员工信息</a>
</body>
</html>
  • /employee/list.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>员工列表</title>
</head>
<body>
<table>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
</tr>
<c:forEach items="${requestScope.employees}" var="employee">
<tr>
<td>${employee.id }</td>
<td>${employee.lastName }</td>
<td>${employee.email }</td>
<td>${employee.gender }</td>
</tr>
</c:forEach>
</table>
</body>
</html>

SQL 映射文件

提示

根据上面的 application-context.xml 配置文件,SQL 映射文件统一存放在 /src/main/resources/mapper 目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.clay.mybatis.dao.EmployeeMapper">

<select id="queryAll" resultType="Employee">
select id, last_name, gender, email
from t_employee
</select>

<delete id="delEmpById" parameterType="Long">
delete from t_employee
where id = #{id}
</delete>

</mapper>

项目代码测试

在 Eclipse 内将项目部署到 Tomcat 服务器,然后浏览器打开 http://127.0.0.1:8080/ssm-study/employee/list/,若看到下面的页面内容,则说明 Spring 成功整合了 MyBatis。

项目完整的目录结构图