1.MyBatis工作原理
如下图所示
MyBatis框架在操作数据库时,大体经过了8个步骤。下面结合MyBatis工作原理图对每一步流程进行详细讲解,具体如下。
(1)MyBatis读取核心配置文件mybatis-config.xml: mybatis-config.xml核心配置文件主要配置了MyBatis的运行环境等信息。
(2)加载映射文件Mapper.xml: Mapper.xml文件即SQL映射文件,该文件配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。
(3)构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory, 用于创建SqlSession。
(4)创建会话对象:由会话工厂SqlSessionFactory创建SqlSession对象, 该对象中包含了执行SQL语句的所有方法。
(5)创建执行器:会话对象本身不能直接操作数据库,MyBatis底层定义了一个Executor接口用于操作数据库,执行器会根据SqlSession传递的参数动态的生成需要执行的SQL语句,同时负责查询缓存地维护。
(6)封装SQL信息:SqlSession内部通过执行器Executor操作数据库, 执行器将待处理的SQL信息封装到MappedStatement对象中。
(7)操作数据库:根据动态生成的SQL操作数据库。
(8)输出结果映射:执行SQL语句之后,通过MappedStatement对象将输出结果映射至Java对象中。
2.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" >
3.MyBatis映射文件
mybatis的顶级的几个元素
cache
– 该命名空间的缓存配置。cache-ref
– 引用其它命名空间的缓存配置。resultMap
– 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。insert
– 映射插入语句。update
– 映射更新语句。delete
– 映射删除语句。select
– 映射查询语句。
查询语句是 MyBatis 中最常用的元素之一
<select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="personResultMap" flushCache="false" useCache="true" timeout="10" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY"> <insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"> <update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"> <delete id="deleteAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20">
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以根据语句中实际传入的参数计算出应该使用的类型处理器(TypeHandler),默认值为未设置(unset)。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset )。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
4.动态SQL
1.if
<select id="fe" resultType="">
<if test=" ">
</if>
</select>
2.choose
<select id="" resultType=""> <choose> <when test=""> </when> <when test=""> </when> <otherwise> </otherwise> </choose> </select>
3.where
<select id="" esultType=""> <where> <if test="l"> </if> <if test=""> </if> <if test=""> </if> </where> </select>
4.forach
<select id=""> select * from .... <where> <foreach item="item" index="index" collection="list" open="ID in (" separator="," close=")" nullable="true"> #{item} </foreach> </where> </select>
5.关联关系
1.一对一
一对一指的是一个对象与另一个对象之间是一对一的关系,例如一个学生只能对应一个班级。
2.一对多
一对多指的是一个对象与多个对象之间是一对多的关系,例如一个班级可以有多个学生。
3.多对多
多对多指的是多个对象之间互相关联,例如一个学生可以参加多个兴趣小组,而一个兴趣小组也可以有多个学生参加。
在 Java 中,一对一、一对多、多对多的关系也可以通过不同的数据结构来表示:
- 一对一的关系可以使用类中的属性来表示。
- 一对多的关系可以使用 List 或 Set 集合来表示,其中 List 表示有序多个元素,Set 表示无序不重复的多个元素。
- 多对多的关系可以使用关联表(junction table)来表示,关联表中包含关联两个对象的外键(foreign key)信息。
这些关系的建立和使用都需要考虑到数据的完整性和一致性,例如需要使用事务来确保多个操作的原子性。
6.一级缓存和二级缓存
1.一级缓存
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。
用户发起查询请求,查找某条数据,sqlSession先去缓存中查找,是否有该数据,如果有,读取;
如果没有,从数据库中查询,并将查询到的数据放入一级缓存区域,供下次查找使用。
但sqlSession执行commit,即增删改操作时会清空缓存。这么做的目的是避免脏读。
2.二级缓存
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
打开二级缓存需在mybatis核心配置文件中加入
<setting name="lazyLoadingEnabled" value="true" />