简介 {#简介}
- 什么是 Mybatis ?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- Mybatis 历史
Mybatis 是 Apache 软件基金会下的一个开源项目, 前身是 ibatis 框架。 2010 年这个项目由 apache 软件基金会迁移到 google code 下, 改名为 Mybatis。 2013 年 11 月又迁移到了 github。
- 通俗说 Mybatis 到底可以做什么?
平时我们都用 JDBC 访问数据库,除了需要自己写 SQL 之外,还必须操作 Connection, Statement, ResultSet,这些其实只是手段的辅助类。 不仅如此,访问不同的表,还会写很多相同的代码,显得繁琐和枯燥。
那么用了 Mybatis 之后,只需要自己提供 SQL 语句,其他的工作,诸如建立连接 Statement, JDBC 相关异常处理等等都交给 Mybatis 去做了,那些重复性的工作 Mybatis 也给做掉了,开发者只需要关注在增删改查等操作层面上,而 Mybatis 把技术细节都封装在了我们看不见的地方。
框架原理 {#框架原理}
图说: {#图说:}
1、Mybatis 配置文件 SqlMapConfig.xml :此文件作为 mybatis 的全局配置文件,定义了 mybatis 运行的基础环境信息,如数据库链接信息等。mapper.xml 文件,这些文件是 sql 映射文件,文件配置了操作数据库的 sql 语句,此文件需要在 SqlMapConfig.xml 中配置加载。
2、通过 mybatis 环境等配置信息构造 SqlSessionFactory,即会话工厂。
3、由会话工厂创建 sqlSession 即会话,操作数据库需要通过 sqlSession 进行。
4、mybatis 底层自定义了 Executor 执行器接口操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement 也是 mybatis 一个底层封装对象,它包装了 mybatis 配置信息及 sql 映射信息等。mapper.xml 文件中一个 sql 对应一个 Mapped Statement 对象,sql 的 id 即是 Mapped statemen t 的 id。
6、Mapped Statement 对 sql 执行输入参数进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 前将输入的 java 对象映射至 sql 中,输入参数映射就是 jdbc 编程中对 preparedStatement 设置参数。
7、Mapped Statement 对 sql 执行输出结果进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 后将输出结果映射至 java 对象中,输出结果映射过程相当于 jdbc 编程中对结果的解析处理过程。
搭建入门案例 {#搭建入门案例}
环境说明:
- JDK:1.8
- mybatis:3.5.7
- maven 工程
1、创建 maven 工程,导入依赖
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
2、创建实体类
@ToString
@Getter
@Setter
@Builder
public class User {
Integer id;
String account;
String name;
String password;
}
3、用户接口
public interface UserDao {
<span class="token comment">/**
* 保存
*/</span>
<span class="token keyword">int</span> <span class="token function">savaUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"user"</span><span class="token punctuation">)</span> <span class="token class-name">User</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 查询
*/</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">User</span><span class="token punctuation">></span></span> <span class="token function">findByid</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 添加
*/</span>
<span class="token keyword">int</span> <span class="token function">addUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token keyword">int</span> id<span class="token punctuation">,</span> <span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"user"</span><span class="token punctuation">)</span> <span class="token class-name">User</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 删除
*/</span>
<span class="token keyword">int</span> <span class="token function">deleteById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
4、编写配置文件
在 resources 文件夹中,创建 Mybatis 的主配置文件 SqlMapConfig.xml。它是 mybatis 核心配置文件,配置文件内容为数据源、事务管理。
配置环境:
配置 mysql 的环境:
- 配置事务的类型;
- 配置连接池:配置连接数据库的 4 个基本信息;
指定映射配置文件的位置:
<?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>
<!-- 数据源配置 -->
<!--
default: 当前环境默认数据库环境
-->
<environments default="mysql">
<!-- id: 每个数据库环境的 ID -->
<environment id="mysql">
<!-- 事务管理器,事务控制
jdbc: 数据源事务管理器 ,类似 Spring 的 DataSourceTransactiionManager -->
<transactionManager type="JDBC"></transactionManager>
<!-- type: 连接池类型
POOLED: 使用 mybatis 自带的数据源
UNPOOLED: 不使用数据源 -->
<dataSource type="POOLED">
<!-- 数据库链接配置 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mappers</span><span class="token punctuation">></span></span>
<span class="token comment"><!--
1、指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件
2、路径必须是反斜杠
--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mapper</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com/mobaijun/dao/mapper/UserDao.xml<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mappers</span><span class="token punctuation">></span></span>
</configuration>
5、映射文件,目录地址:com.mobaijun.dao.mapper.*.xml
<?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.mobaijun.dao.UserDao">
<resultMap id="BaseResultMap" type="com.mobaijun.entity.User">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="account" property="account" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/>
</resultMap>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sql</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Column_List<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
id,`name`,account,password
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sql</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>saveUser<span class="token punctuation">"</span></span> <span class="token attr-name">parameterType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com.mobaijun.entity.User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
INSERT INTO `user`(`id`, `account`, `name`, `password`)
VALUES (#{id}, #{account}, #{name}, #{password});
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>delete</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>deleteById<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
DELETE
FROM user
WHERE id = ${id}
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>delete</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>findByid<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>BaseResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
SELECT
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>include</span> <span class="token attr-name">refid</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Column_List<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
FROM user WHERE id=#{id};
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>findAll<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com.mobaijun.entity.User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
SELECT
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>include</span> <span class="token attr-name">refid</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Column_List<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
FROM user
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span>
</mapper>
- 参数说明
- namespace:用来区别不同的类的名字
- id: 标识映射文件中的 sql,称为 statement 的 id 将 sql 语句封装到 mappedStatement 对象中,所以将 id 称为 statement 的 id
- sql:里面为表所有字段,可自定义或添加别名。
- parameterType: 指定输入参数的类型.
- resultType: 指定输出结果类型。mybatis 将 sql 查询结果的一行记录数据映射为 resultType 指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器 List 中
1、#{}: 一个占位符。preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换。#{} 可以有效防止 sql 注入。 #{} 可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称。
2`、$`{}`: 表示拼接 sql 串,通过 $`{}`可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,$`{}`可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,$`{}`括号中只能是 value。`
6、编写测试类
在 test->java 目录下创建测试类 com.mobaijun.test.MybatisTest。实现业务需求,共 7 步。
1. 扫描 mappper 配置文件 `SqlMapConfig.xml`
2. 创建 `SqlSessionFactoryBuilder` 工厂
3. 创建 `SqlSessionFactory` 工厂
4. 创建 `SqlSession`,包含 `CRUD` 方法
5. 获取 Mapper 接口的代理对象
6. 使用代理执行 CRUD 操作
7. 关闭资源
- 示例代码
@Slf4j
@SpringBootTest
public class MybatisTest {
<span class="token comment">/**
* 根据 id 查询
*/</span>
<span class="token annotation punctuation">@SneakyThrows</span>
<span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 1. 读取配置文件</span>
<span class="token class-name">InputStream</span> in <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"SqlMapConfig.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. 创建 SqlSessionFactory 工厂</span>
<span class="token class-name">SqlSessionFactory</span> build <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>in<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 3. 使用工厂生产 SqlSession 对象</span>
<span class="token class-name">SqlSession</span> session <span class="token operator">=</span> build<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 4. 执行 Sql 语句</span>
<span class="token class-name">UserDao</span> userDao <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">UserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"代理对象:"</span> <span class="token operator">+</span> userDao<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 5. 打印结果</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">User</span><span class="token punctuation">></span></span> list <span class="token operator">=</span> userDao<span class="token punctuation">.</span><span class="token function">findByid</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 输出结果:User(id=1, account=mobai, name= 墨白, password=123456)</span>
list<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token operator">::</span><span class="token function">println</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 6. 释放资源</span>
session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
in<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* 删除
*/</span>
<span class="token annotation punctuation">@SneakyThrows</span>
<span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteById</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 1. 读取配置文件</span>
<span class="token class-name">InputStream</span> in <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"SqlMapConfig.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. 创建 SqlSessionFactory 工厂</span>
<span class="token class-name">SqlSessionFactory</span> build <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>in<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 3. 使用工厂生产 SqlSession 对象</span>
<span class="token class-name">SqlSession</span> session <span class="token operator">=</span> build<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 4. 执行 Sql 语句</span>
<span class="token class-name">UserDao</span> userDao <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">UserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"代理对象:"</span> <span class="token operator">+</span> userDao<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 5. 执行 SQL</span>
userDao<span class="token punctuation">.</span><span class="token function">deleteById</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 6. 释放资源</span>
session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
in<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* 新增
*/</span>
<span class="token annotation punctuation">@SneakyThrows</span>
<span class="token annotation punctuation">@Test</span>
<span class="token annotation punctuation">@Rollback</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">saveUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 1. 读取配置文件</span>
<span class="token class-name">InputStream</span> in <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"SqlMapConfig.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. 创建 SqlSessionFactory 工厂</span>
<span class="token class-name">SqlSessionFactory</span> build <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>in<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 3. 使用工厂生产 SqlSession 对象</span>
<span class="token class-name">SqlSession</span> session <span class="token operator">=</span> build<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 4. 执行 Sql 语句</span>
<span class="token class-name">UserDao</span> userDao <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">UserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">User</span> user<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
user <span class="token operator">=</span> <span class="token class-name">User</span><span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">account</span><span class="token punctuation">(</span><span class="token string">"mobai123"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">name</span><span class="token punctuation">(</span><span class="token string">"mobaijun"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">password</span><span class="token punctuation">(</span><span class="token string">"123456"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"代理对象:"</span> <span class="token operator">+</span> userDao<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 5. 执行 SQL</span>
userDao<span class="token punctuation">.</span><span class="token function">saveUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 6. 提交数据</span>
session<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 7. 释放资源</span>
session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
in<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
基于原始 Dao 实现 CRUD {#基于原始 -Dao- 实现 -CRUD}
需要自行实现 dao 接口和 dao 实现类,即 UserDao 和 UserDaoImpl 实现类。
原始 Dao 开发存在以下问题
- Dao 方法体存在重复代码:通过 SqlSessionFactory 创建 SqlSession,调用 SqlSession 的数据库操作方法
- 调用 sqlSession 的数据库操作方法需要指定 statement 的 id,这里存在硬编码,不得于开发维护。
持久层 Dao 接口
@Mapper
public interface TestUserDao {
<span class="token comment">/**
* 通过 ID 查询一个用户
*/</span>
<span class="token class-name">TestUser</span> <span class="token function">findUserById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token class-name">Integer</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 根据用户名模糊查询用户列表
*/</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">TestUser</span><span class="token punctuation">></span></span> <span class="token function">findUserByUserName</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"name"</span><span class="token punctuation">)</span> <span class="token class-name">String</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 添加用户
*/</span>
<span class="token keyword">int</span> <span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token class-name">TestUser</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 更新用户
*/</span>
<span class="token keyword">void</span> <span class="token function">updateUserById</span><span class="token punctuation">(</span><span class="token class-name">TestUser</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* 删除用户
*/</span>
<span class="token keyword">void</span> <span class="token function">deleteUserById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token class-name">Integer</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
实现类
public class TestUserDaoImpl implements TestUserDao {
<span class="token keyword">private</span> <span class="token class-name">SqlSessionFactory</span> sqlSessionFactory<span class="token punctuation">;</span>
<span class="token comment">/**
* 通过构造方法注入
*/</span>
<span class="token keyword">public</span> <span class="token class-name">TestUserDaoImpl</span><span class="token punctuation">(</span><span class="token class-name">SqlSessionFactory</span> sqlSessionFactory<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>sqlSessionFactory <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">TestUser</span> <span class="token function">findUserById</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// sqlSession 是线程不安全的,所以它的最佳使用范围在方法体内</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUserDao</span> mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">TestUserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUser</span> user <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">findUserById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> user<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">TestUser</span><span class="token punctuation">></span></span> <span class="token function">findUserByUserName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUserDao</span> mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">TestUserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">TestUser</span><span class="token punctuation">></span></span> userList <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">findUserByUserName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> userList<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token class-name">TestUser</span> user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUserDao</span> mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">TestUserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> i <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">insertUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> i<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">updateUserById</span><span class="token punctuation">(</span><span class="token class-name">TestUser</span> user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUserDao</span> mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">TestUserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
mapper<span class="token punctuation">.</span><span class="token function">updateUserById</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteUserById</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TestUserDao</span> mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">TestUserDao</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
mapper<span class="token punctuation">.</span><span class="token function">deleteUserById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sqlSession<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
映射文件
<?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.mobaijun.dao.TestUserDao">
<resultMap id="BaseResultMap" type="com.mobaijun.entity.TestUser">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="account" property="account" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/>
</resultMap>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sql</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Column_List<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
id,`name`,account,password
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sql</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 添加用户 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>insertUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
INSERT INTO `user` (`id`, `account`, `name`, `password`)
VALUES (#{id}, #{account}, #{name}, #{password});
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 更新用户 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>update</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>updateUserById<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
UPDATE `test`.`user`
SET `account` = #{account},
`name` =#{name},
`password` = #{password}
WHERE `id` = #{id};
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>update</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 根据 id 删除一个用户 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>delete</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>deleteUserById<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
delete
from user
where id = #{id}
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>delete</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 通过 Id 查询一个用户 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>findUserById<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com.mobaijun.entity.TestUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
SELECT
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>include</span> <span class="token attr-name">refid</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Column_List<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
FROM `user`
WHERE id = #{id}
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 根据用户名模糊查询用户列表 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>findUserByUserName<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com.mobaijun.entity.TestUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
SELECT *
FROM `user`
WHERE name LIKE '%'#{name}'%'
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span>
</mapper>
Mybatis 配置文件
<?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>
<!-- 数据源配置 -->
<environments default="mysql">
<!-- 配置 MySQL 环境 -->
<environment id="mysql">
<!-- 配置事务类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接池 -->
<dataSource type="POOLED">
<!-- 数据库链接配置 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mappers</span><span class="token punctuation">></span></span>
<span class="token comment"><!--
1、指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件
2、* 表示通配符,表示 mapper 目录下所有以 .xml 后缀结尾的文件
--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mapper</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com/mobaijun/dao/mapper/UserDao.xml<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mapper</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>com/mobaijun/dao/mapper/TestUserDao.xml<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mappers</span><span class="token punctuation">></span></span>
</configuration>
源码地址:spring-boot-mybatis