MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
XML 配置
更多配置参考:官方文档 XML配置项
1 |
|
数据库连接池:
一个中间层,初始化多个连接,建立连接从连接池取出,断开连接放回连接池,开销比直接连接断开小得多。
XML 映射
占位符的区别
#{}
: 对非字符串参数的占位符,可以有效防止 SQL 注入- 入参是简单数据类型(除 String),
#{}
内可以任意写 - 入参是对象类型,
#{}
内必须是对象成员变量名称
- 入参是简单数据类型(除 String),
${}
: 对字符串的拼接替换,可以替换列名和表名,存在 SQL 注入风险,尽量少用- 入参是基本数据类型(有 String),
${}
内必须是value
- 入参是对象类型,
${}
内必须是对象成员变量名称
- 入参是基本数据类型(有 String),
使用
#{}
防止 SQL 注入:
- 遇到模糊查询需要拼接字符串时:
where name like '%${name}%'
- 使用
concat
函数改为:where name like concat('%',#{name},'%')
字符串替换只能使用
${}
,详见下一节代码
创建映射配置文件
更多配置参考:官方文档 XML映射器
1 |
|
测试使用
增删改需要 commit !!!
1 | public class MyTest { |
动态代理
动态代理后就不需要从 xml 中取出执行方法,通过统一的代理接口直接调用。
创建代理接口
1 | package com.proj.mapper; |
修改配置文件
更改为代理接口的 reference
1 | <mappers> |
测试使用
1 | public class MyTest { |
动态 SQL
官方文档:动态SQL
动态 SQL 使条件判断更为简单:
- 定义代码片段
- 逻辑判断
- 循环(批量)处理
<sql>
和 <include>
<sql>
:定义代码片段<include>
:使用代码片段。
1 | <mapper namespace="com.proj.mapper.UsersMapper"> |
<if>
<if>
:条件判断
<where>
<where>
:多条件拼接,在查删改使用
多条件拼接:
1 | <select id="getByCondition" parameterType="users" resultType="users"> |
测试:
1 |
|
<set>
set
:有选择地进行更新处理,至少更新一列
有选择地更新:
1 | <update id="updateBySet" parameterType="users"> |
测试:
1 |
|
<foreach>
<foreach>
:循环遍历,完成循环条件查询,批量增删改
批量操作:
1 | <select id="getByIds" resultType="users"> |
测试:
1 |
|
批量更新
允许多行操作:在 jdbc.properties
中的数据库 url 中添加 &allowMultiQueries=true
1 | <update id="updateBySet" parameterType="users"> |
Map
入参多个
入参多个,可以指定参数位置传参,是实体类包含不住的条件。
实体类只能封装成员变量的条件,如果某个成员变量有区间范围的判断,或有两个值处理,则实体类无法包含。
根据生日范围查询:
1 | <!-- |
也可以和动态代理里一样,用
@param
区分参数
入参 Map
入参超过 1 个以上,使用 map 封装查询条件,查询条件更明确。
map 的 key 和 xml 中的参数名对应
1 | <!-- |
返回 Map
如果返回的数据实体类无法包含,可以使用 map 返回多张表的数据,返回数据没有任何关系,都是 Object 类型。
返回的 map 的 key 是列名或别名。
返回一行 map
1 | <!-- |
1 |
|
返回多行 map
1 | <!-- |
resultMap
使用 resultMap
手动完成映射:
property
:实体类成员变量名column
:数据库列名
1 | <resultMap id="myMap" type="users"> |
1 |
|
一对多关系
一个老师有多个学生,假定
- 老师:
id
、name
、studentList
- 学生:
id
、name
1 | <!-- 绑定老师 --> |
多对一关系
学生对应绑定的老师,假定
- 老师:
id
、name
、studentList
- 学生:
id
、name
、teacher
1 | <!-- 绑定学生 --> |
studentList
不用绑定,否则循环绑死
一对一关系
一个班级对应一个班级,一个班级对应一个老师。
用 association
多对多关系
一个文章对应多个标签,一个标签对应多个文章,两个表就是多对多关系。
通过建立中间表处理多对多关联。
用 collection
无论什么关联关系:
- 一方持有另一方的集合,使用
<collection>
- 一方持有另一方的对象,使用
<association>
事务
简而言之,多个 CRUD 操作对应一个事务操作。
在 MyBatis 框架中设置事务:
<transactionManager type="JDBC"/>
:程序员自己控制提交和回滚
可设置为自动提交:
sqlSession = factory.openSession(true);
:默认是 false,手动提交之后不需要手动 commit
缓存
Mybatis 提供两级缓存:一级缓存和二级缓存,默认开启一级缓存。
查询流程
缓存查询流程:
- 查询先查缓存,如果没有则查询数据库,存在缓存中,再返回给客户端
- 下次访问相同查询时,直接从缓存返回
- 如果数据库发生 commit 操作,则清空缓存
作用域
- 一级缓存:使用
sqlSession
的作用域,同一个sqlSession
共享一级缓存的数据 - 二级缓存:使用
mapper
的作用域,不同sqlSession
只要访问同一个mapper.xml
文件,则共享二级缓存的数据。
ORM(Object Relational Mapping)即对象关系映射:
Java 语言中以对象的方式操作数据,数据库中以表的方式存储,对象中的成员变量与表中的列之间的数据互换。