Spring MyBatis
MyBatis
- MyBatis是一款优秀的持久层框架,用于简化JDBC的开发
- 官网:MyBatis 3
快速入门
引入MyBatis依赖
可以在创建SpringBoot项目时,勾选相关依赖:

注意:由于是与MySQL数据库进行操作,所以别忘了添加MySQL驱动依赖(其他数据库同理)
也可以在pom.xml中引入依赖:
1 | <dependency> |
编写MyBatis配置
通常在项目的resource/application.properties文件中进行相关配置的编写,主要是关于数据库的连接信息
配置信息如下:
1 | # 配置数据库连接信息 |
根据自己的数据库配置进行适当修改
如果需要在控制台中输出SQL语句的日志信息,可以添加以下配置:
1 | mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl |
创建Mapper接口
关键字:@Mapper
一般有了MyBatis,只需要创建Mapper接口即可,不需要对接口编写实现类(底层会自动生成实现类对象)
1 | package com.norlcyan.mapper; |
应用程序在运行时,会自动为该接口创建一个实现类对象(代理对象),并且会自动将该类的实现对象放到IOC容器中
增删改查
MyBatis的增删改查注解都对应了SQL语句中的关键字:@Insert、@Delete、@Update、@Select
以删除为例,当条件语句中的参数是动态的情况,可以利用#{数据}的形式作为占位符:
1 |
|
其中,DML语句(增删改)可以设置为无返回值也可以设置带有返回值。如果带有返回值,那返回值类型需要为Integer,且该返回值的类型表示的是被影响的行数
形参也可以为实体类(比如User),但是占位符的名称需要和类中成员属性名称完全一致
如果遇到字段为自增的情况,可以将实体类中的成员属性设置为null。或者利用
@Options注解,这种方式还可以获取到数据库中自增后的值
虽然冷门但是面试题:除了#{数据},还有${...}。但是${...}表示的是将括号内的内容直接拼接到SQL语句中,类似于拼接符,这种形式不安全存在SQL注入问题,且性能低,几乎不用这种形式(除非是需要动态表名或字段名)
@Param注解
该注解主要是用于给形参起名,让SQL语句中的占位符可以对应上形参(编译后只会保留形参类型,不会保留形参名):
1 | ; |
当方法的形参类型相同,且有多个形参时,需要使用@Param注解为其形参起名
如果基于官方骨架创建的SpringBoot项目,接口编译时会保留方法形参名,此时@Param注解可以省略,但是形参名需要和占位符名对应
XML映射
- 在MyBatis中,既可以通过注解配置SQL语句,也可以通过XML配置文件配置SQL语句
- 默认规则:
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中SQL语句的id与Mapper接口中的方法一致,并保持返回类型一致
假设当前的Mapper接口如下:
1 | package com.norlcyan.mapper; |
将其改造为使用XML映射的方式:
- 先去除注解
1 | package com.norlcyan.mapper; |
有XML映射文件就不要使用注解,有注解就不要使用XML映射文件
简单的SQL语句可以交给注解,复杂的SQL语句还是XML映射文件更好
- 创建XML文件:
1 |
|
namespace表示映射的Mapper接口,参数填入该接口的全类名
resultType 只需要指定实体类的全限定名,而**不需要关心是返回单个对象还是集合**
parameterType 实际上是可以省略的,MyBatis 可以根据方法参数自动推断参数类型。不省略的好处在于可读性更好
- 最重要的一步,将XML文件存放在指定位置:

辅助配置
配置XML映射文件的位置:
1 | mybatis.mapper-locations=classpath:mapper/*.xml |
java目录和resource目录编译后都会存放在类路径下(classpath)
所以配置中表达的意思是在resource/mapper目录下,查找所有的xml文件
推荐IDEA MyBatis插件:MyBatisX
JDBC与MyBatis

数据库连接池
数据库连接池是个**容器**,负责分配、管理数据库连接(Connection)
它运行应用程序**重复使用**一个现有的数据库连接,而不是再重新建立一个
释放空间时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
优势:
- 资源复用
- 提升系统响应速度
- 避免数据库连接遗漏
标准接口:DataSource
- 官方提供的数据库连接池接口,由第三方组织实现此接口
- 功能:获取连接
Connection getConnection() throws SQLException;
常见产品:
- C3P0(使用较少)
- DBCP(使用较少)
- Druid
- Hikari(SpringBoot默认)
Druid连接池是阿里巴巴开源的数据库连接池项目
功能强大性能优秀,是Java最好的数据库连接池之一
切换连接池
安装连接池依赖:
1 | <dependency> |
修改配置文件:
1 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource |
MyBatis动态SQL语句
核心动态SQL标签
| 标签 | 作用 | 适用场景 | 示例 |
|---|---|---|---|
<if> |
条件判断 | 根据条件包含SQL片段 | 查询条件动态拼接 |
<choose><when><otherwise> |
多条件选择 | 类似switch-case逻辑 | 多选一条件判断 |
<where> |
动态WHERE子句 | 自动处理WHERE和AND/OR | 动态查询条件 |
<set> |
动态SET子句 | 自动处理SET和逗号 | 动态更新字段 |
<foreach> |
循环遍历 | 集合遍历处理 | IN查询、批量操作 |
<trim> |
自定义trim | 自定义前缀后缀处理 | 复杂SQL片段处理 |
<bind> |
创建变量 | 创建OGNL变量 | 字符串处理、复用 |
条件判断标签
<if> 标签
1 | <select id="findActiveBlogWithTitleLike" resultType="Blog"> |
适用场景:简单的条件判断,当条件满足时包含SQL片段
<choose> 标签
1 | <select id="findActiveBlogLike" resultType="Blog"> |
适用场景:多条件选择,类似编程语言中的switch-case语句
动态SQL片段标签
<where> 标签
1 | <select id="findActiveBlogLike" resultType="Blog"> |
适用场景:动态WHERE子句,自动处理多余的AND/OR和空WHERE
<set> 标签
1 | <update id="updateAuthorIfNecessary"> |
适用场景:动态UPDATE语句的SET子句,自动处理多余的逗号
<foreach> 标签
1 | <select id="selectPostIn" resultType="domain.blog.Post"> |
适用场景:集合遍历,处理IN查询、批量插入等
属性:
- collection:集合名词
- item:遍历出的单个元素
- separator:每一次遍历使用的分隔符(可选)
- open:遍历开始前拼接的片段(可选),注意是整个遍历开始前
- close:遍历结束后拼接的片段(可选),注意是整个遍历结束后
<trim> 标签
1 | <update id="updateAuthorIfNecessary"> |
适用场景:自定义SQL片段处理,更灵活的前缀后缀控制
<bind> 标签
1 | <select id="selectBlogsLike" resultType="Blog"> |
适用场景:创建可在其他部分使用的变量,常用于字符串处理
SQL复用标签
<sql> 和 <include> 标签
1 | <sql id="userColumns">id, username, password, email</sql> |
适用场景:SQL片段复用,避免重复代码
常用动态SQL模式
1. 动态查询
1 | <select id="selectByCondition" resultType="User"> |
2. 动态更新
1 | <update id="updateUser" parameterType="User"> |
3. 批量插入
1 | <insert id="batchInsert"> |
4. IN查询
1 | <select id="selectByIds" resultType="User"> |
注意事项
- 参数引用:使用
#{}防止SQL注入,使用${}直接拼接(慎用) - 集合处理:collection属性可为list、array或Map的key
- OGNL表达式:test属性中可使用复杂的OGNL表达式
- 空值处理:注意字符串空值和null值的区别
- 性能考虑:复杂动态SQL可能影响查询计划缓存
MyBatis 常用注解总结
核心注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@Select |
方法 | 定义查询SQL | 数据查询操作 | @Select("SELECT * FROM emp WHERE id = #{id}") |
@Insert |
方法 | 定义插入SQL | 数据插入操作 | @Insert("INSERT INTO emp(username) VALUES(#{username})") |
@Update |
方法 | 定义更新SQL | 数据更新操作 | @Update("UPDATE emp SET name = #{name} WHERE id = #{id}") |
@Delete |
方法 | 定义删除SQL | 数据删除操作 | @Delete("DELETE FROM emp WHERE id = #{id}") |
结果映射注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@Results |
方法 | 定义结果映射集合 | 复杂字段映射 | @Results({@Result(column="dept_id", property="deptId")}) |
@Result |
方法内 | 定义单个结果映射 | 字段名与属性名不一致时 | @Result(column="create_time", property="createTime") |
@ResultMap |
方法 | 引用XML中定义的resultMap | 复用XML映射配置 | @ResultMap("EmpResultMap") |
主键相关注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@Options |
方法 | 配置SQL执行选项 | 主键生成、缓存等 | @Options(useGeneratedKeys=true, keyProperty="id") |
@SelectKey |
方法 | 自定义主键生成 | 特殊主键生成策略 | @SelectKey(statement="SELECT SEQ.NEXTVAL", keyProperty="id", resultType=int.class, before=true) |
动态SQL注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@SelectProvider |
方法 | 动态生成查询SQL | 复杂动态查询 | @SelectProvider(type=EmpSqlProvider.class, method="getEmpByCondition") |
@InsertProvider |
方法 | 动态生成插入SQL | 复杂动态插入 | @InsertProvider(type=EmpSqlProvider.class, method="insertEmp") |
@UpdateProvider |
方法 | 动态生成更新SQL | 复杂动态更新 | @UpdateProvider(type=EmpSqlProvider.class, method="updateEmp") |
@DeleteProvider |
方法 | 动态生成删除SQL | 复杂动态删除 | @DeleteProvider(type=EmpSqlProvider.class, method="deleteEmp") |
参数绑定注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@Param |
参数 | 指定参数名称 | 多参数方法 | findByNameAndAge(@Param("name") String name, @Param("age") Integer age) |
@MapKey |
方法 | 指定Map的key | 返回Map集合 | @MapKey("id") Map<Integer, Emp> findAll(); |
缓存相关注解
| 注解 | 作用域 | 说明 | 适用场景 | 示例 |
|---|---|---|---|---|
@CacheNamespace |
类 | 配置二级缓存 | 启用Mapper级别缓存 | @CacheNamespace |
@CacheNamespaceRef |
类 | 引用其他Mapper缓存 | 共享缓存配置 | @CacheNamespaceRef(EmpMapper.class) |
常用注解详细说明
1. CRUD基础注解
@Select 查询注解
1 |
|
@Insert 插入注解
1 |
|
@Update 更新注解
1 |
|
@Delete 删除注解
1 |
|
2. 结果映射注解
@Results 和 @Result
1 |
|
3. 动态SQL提供者
SQL提供者类
1 | public class EmpSqlProvider { |
使用提供者
1 |
|
4. 多参数处理
使用@Param
1 |
|
最佳实践建议
- 简单SQL使用注解:对于简单的CRUD操作,直接使用注解更简洁
- 复杂SQL使用XML:对于复杂的动态SQL,建议使用XML配置
- 主键回填:插入操作记得使用
@Options(useGeneratedKeys=true) - 参数命名:多参数方法使用
@Param明确参数名称 - 结果映射:字段名与属性名不一致时使用
@Results注解
这些注解可以帮助您快速构建MyBatis数据访问层,提高开发效率。