目录

mybatis整合spring

概述

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

官方文档

源码仓库

官方整合示例

工程目录:

20201010172726

处理依赖

ssm: spring + spring mvc + mybatis

版本要求

MyBatis-Spring 需要以下版本:

MyBatis-Spring MyBatis Spring 框架 Spring Batch Java
2.0 3.5+ 5.0+ 4.0+ Java 8+
1.3 3.4+ 3.2.2+ 2.1+ Java 6+

pom依赖

  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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>eden</artifactId>
        <groupId>com.eh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ssm</artifactId>
    <packaging>war</packaging>

    <name>ssm Maven Webapp</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <springframework.version>5.2.8.RELEASE</springframework.version>
        <javax.servlet-api.version>3.1.0</javax.servlet-api.version>
        <jsp-api.version>2.2</jsp-api.version>
        <jstl.version>1.2</jstl.version>
        <mysql-connector-java.version>6.0.6</mysql-connector-java.version>
    </properties>

    <dependencies>
        <!--mybatis核心包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

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

        <!--mybatis整合spring包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>

        <!-- 整合Spring -->
        <!--
        从Spring 3.2开始不需要定义CGLIB依赖(目前的版本是CGLIB 3.0)。现在使用内嵌在spring-core JAR
        commons-logging日志jar包也无需单独引入,spring已引入
        -->
        <!--BEGIN IOC-->
        <!--Context,提供上下文、全局配置,实现了Spring注入容器并且依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--核心组件-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--管理beans,JavaBean机制-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--Spring EL表达式 (SpEL)-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--END IOC-->

        <!--BEGIN JDBC-->
        <!--增加了Hibernate和JPA功能支持,比如HibernateTemplate和JpaTemplate以及一些额外的持久化相关的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--在JDBC数据访问库定义Spring JDBC支持以及JdbcTemplate-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--Spring-tx提供了非常灵活的事务管理抽象-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <!--END JDBC-->


        <!--BEGIN WEB-->
        <!--
        在Maven配置Spring MVC要增加Spring Web和Servlet支持,需要在上面已配置的pom文件中额外增加两个依赖
        spring-webmvc spring-webmvc则在Servlet环境中启用MVC支持
        spring-web  spring-web包包含Servlet和Portlet所需要通用组件
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        由于spring-webmvc依赖于spring-web,所以定义了spring-webmvc依赖后,可以不用显示的在pom定义spring-web
        -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!--END WEB-->

        <!--BEGIN AOP-->
        <!--提供aop框架,将日志输出、权限验证等分离-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${springframework.version}</version>
        </dependency>

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

        <!-- BEGIN Servlet相关依赖包 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${javax.servlet-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jsp-api.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <!-- END Servlet相关依赖包 -->
        <!--TEST-->
        <!--
        从Spring 3.2开始,Spring MVC Test项目已经被包含到核心的Spring Test框架中(原来是一个独立项目,项目托管在GitHub)。
        所以,从Spring 3.2开始,仅需要在依赖配置中配置spring-test依赖即可。
        注意:对于使用Spring 3.1及以下版本的应用来说,独立的spring-mvc-test依赖还是可以使用的,可以参考这里进行配置。
        但是,这个依赖已经不再Maven的中央库中,所以如果需要增加依赖需要配置自定义Maven容器。
        -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${springframework.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- DB连接池 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

        <!--
        mybatis-generator是一款在使用mybatis框架时,自动生成model,dao和mapper的工具,
        很大程度上减少了业务开发人员的手动编码时间
        -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!-- 引入日志包 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.7</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.7</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.4.0</version>
                <configuration>
                    <!-- mybatis用于生成代码的配置文件 -->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <verbose>true</verbose>
                    <!--是否覆盖,单表初创的时候可以覆盖,之后要注意生成器配置里要生成哪些表,切勿覆盖稳定版的表映射-->
                    <overwrite>true</overwrite>
                </configuration>
                <executions>
                    <execution>
                        <id>Generate MyBatis Artifacts</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>${mysql-connector-java.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

</project>

引入mybatis之前的配置

变化:

  • sql映射文件放在mybatis/mapper文件夹下,原先是和java类放在同一个类路径下,和spring整合后已经解决了这个问题,无需再放在同一类路径下。

springmvc配置

springmvc控制网站跳转逻辑

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">


  <!--让spring ioc容器跟随web容器一起启动,需要配置ContextLoadListener-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--指定spring配置文件的位置-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <!--
    classpath 和 classpath* 区别:
    classpath:只会到你的class路径中查找找文件;
    classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找.
    -->
    <param-value>classpath:application.xml</param-value>
  </context-param>

  <!--SpringMVC配置-->
  <!--spring mvc配置文件默认和WEB-INF 同路径 spring-servlet.xml-->
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

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

</web-app>

spring-servlet.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
<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--
    如果在web.xml中servlet-mapping的url-pattern设置的是/,而不是如.do。
    表示将所有的文件,包含静态资源文件都交给spring mvc处理。
    就需要用到<mvc:annotation-driven />了。
    如果不加,DispatcherServlet则无法区分请求是资源文件还是mvc的注解,而导致controller的请求报404错误。
    -->
    <!--
    处理动态资源
    注解驱动,以使得访问路径与方法的匹配可以通过注解配置
    -->
    <mvc:annotation-driven/>

    <!--自动扫描所有的组件-->
    <context:component-scan base-package="com.eh.eden.ssm" use-default-filters="false">
        <!--按照注解扫描,只扫描控制器,再使用 use-default-filters="false" 禁用默认的过滤行为-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--
        视图解析器,解析页面地址,Controller层直接返回一个页面名称字符串即可,视图解析器会去解析
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>


    <!--
    处理静态资源
    静态页面,如html,css,js,images可以访问
    -->
    <mvc:default-servlet-handler/>

</beans>

spring配置

spring管理所有的业务逻辑组件

application.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
49
50
51
52
53
54
55
56
57
58
59
60
<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

    <!--
        spring希望管理所有的业务逻辑组件,除了控制层交给spring mvc管理以外都要管理。
    -->
    <context:component-scan base-package="com.eh.eden.ssm">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--spring用来控制业务逻辑,数据源、事务控制、aop等-->
    <!--引入数据库配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${url}"/>
        <property name="driverClass" value="${driver}"/>
        <property name="user" value="${username}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!--spring事务管理器,管理数据源的提交和关闭-->
    <bean id = "dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

    <!--
    整合mybatis,目的
    1. spring管理所有组件,包括mapper的实现类,之后service调用Dao
    可以使用@Autowired 自动注入,不用再从SqlSession工厂获取连接,再从连接得到代理类
    2. spring用来管理事务,spring声明式事务
    -->
    <!--
    原先在mybatis-config中定义的属性,都挪到SqlSessionFactoryBean下进行定义
    SqlSessionFactoryBean创建出SqlSessionFactory对象,不用再拿到mybatis-config流,再从流buildSqlSessionFactory
    -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--configLocation指定mybatis全局配置文件的位置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--指定mapper文件的位置-->
        <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
    </bean>

    <!--
        扫描所有mapper接口的实现,让这些mapper能够自动注入
    -->
    <mybatis-spring:scan base-package="com.eh.eden.ssm.orm.dao"/>
</beans>

此时可以删除mybatis中部分需要的配置了,剩下的配置如下

mybatis-config.xml

 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="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--显式的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

</configuration>

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
package com.eh.eden.ssm.controller;

import com.eh.eden.ssm.orm.bean.Employee;
import com.eh.eden.ssm.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.Map;

@Controller
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @RequestMapping("/employees")
    public String employees(Map<String, Object> map) {
        List<Employee> employees = employeeService.getAllEmployees();
        map.put("employees", employees);
        return "list";
    }
}

EmployeeService

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.eh.eden.ssm.service;

import com.eh.eden.ssm.orm.bean.Employee;
import com.eh.eden.ssm.orm.dao.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    public List<Employee> getAllEmployees() {
        return employeeMapper.getAllEmployees();
    }
}

EmployeeMapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package com.eh.eden.ssm.orm.dao;


import com.eh.eden.ssm.orm.bean.Employee;

import java.util.List;

public interface EmployeeMapper {

    List<Employee> getAllEmployees();

}

Employee

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.eh.eden.ssm.orm.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;


@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Employee implements Serializable {

    private static final long serialVersionUID = 5591903708394742480L;
    private Integer id;
    private String lastName;
    private String gender;
    private String email;

}

EmployeeMapper.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?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.eh.eden.ssm.orm.dao.EmployeeMapper">

    <resultMap id="employee" type="com.eh.eden.ssm.orm.bean.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
    </resultMap>

    <select id="getAllEmployees" resultMap="employee">
        select * from tbl_employee;
    </select>

</mapper>

测试

从页面点击查询所有员工的信息

页面 index.jsp

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>员工</title>
</head>
<body>
<a href="employees">查询所有员工</a>
</body>
</html>

控制层 EmployeeController

返回页面,员工列表页,在WEB-INF下pages文件夹下新建 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
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工列表页</title>
</head>
<body>
<table>
    <c:forEach items="${employees}" var="emp">
        <tr>
            <td>id</td>
            <td>lastName</td>
            <td>email</td>
            <td>gender</td>
        </tr>
        <tr>
            <td>${emp.id}</td>
            <td>${emp.lastName}</td>
            <td>${emp.email}</td>
            <td>${emp.gender}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

启动tomcat,点击查看所有员工

https://gitee.com/lienhui68/picStore/raw/master/null/20201010145931.png