MyBatis 原理介绍

ORM(Object/Relational Mapping),即对象关系映射,它完成面向对象的编程语言到关系数据库的映射。ORM工具的惟一做用是:把持久化对象的保存、修改、删除等操做,转换成对数据库的操做。java

ORM 基本映射关系:

数据表映射类。
数据表的行映射对象(实例)。
数据表的列(字段)映射对象的属性。

MyBatis 简介:

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
MyBatis 避免了几乎全部的 JDBC 代码和手动设置参数以及对结果集的检索封装。
MyBatis 能够对配置和原生 Map 使用简单的 XML 或注解,将接口和Java的POJOs(Plain Old Java Objects(普通的 Java 对象))映射成数据库中的记录。

MyBatis 主要思想是将程序中的大量SQL语句抽取出来,配置在配置文件中,以实现SQL的灵活配置。
MyBatis 并不彻底是一种ORM框架,它的设计思想和ORM类似,只是它容许直接编写SQL语句,使得数据库访问更加灵活。
MyBatis 提供了一种“半自动化”的ORM实现,是一种“SQL Mapping”框架。

MyBatis功能结构

1. API接口层:
提供给外部使用的接口API,开发人员经过这些本地API来操纵数据库。接口层接收到调用请求就会调用数据处理层来完成具体的数据处理。
2. 数据处理层:
负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操做。
3. 基础支撑层:
负责最基础的功能支撑,包括链接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来做为最基础的组件,为上层的数据处理层提供最基础的支撑。

MyBatis 框架结构

1. 加载配置:
MyBatis 应用程序根据XML配置文件加载运行环境,建立SqlSessionFactory, SqlSession,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。(配置来源于两个地方,一处是配置文件,一处是 Java 代码的注解)
2. SQL解析:
当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(能够是Map、JavaBean或者基本数据类型),MyBatis 会根据SQL的ID找到对应的MappedStatement,而后根据传入参数对象对MappedStatment进行解析,解析后能够获得最终要执行的SQL语句和参数。
3. SQL的执行:
SqlSession将最终获得的SQL和参数拿到数据库进行执行,获得操做数据库的结果。
4. 结果映射:
将操做数据库的结果按照映射的配置进行转换,能够转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回,用完以后关闭SqlSession。

SqlSessionFactory:

每一个基于MyBatis的应用都是以一个SqlSessionFactory的实例为核心的。
SqlSessionFactory是单个数据库映射关系通过编译后的内存映像。
SqlSessionFactory的实例能够经过SqlSessionFactoryBuilder得到。
而SqlSessionFactoryBuilder则能够从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
SqlSessioFactory是建立SqlSession的工厂。

SqlSession:

SqlSession是执行持久化操做的对象,它彻底包含了面向数据库执行SQL命令所需的全部方法。
能够经过SqlSession实例来直接执行已映射的SQL语句,在使用完SqlSession后咱们应该使用finally块来确保关闭它。

Mybatis.xml 配置文件:

配置文件包括:
1. configuration 配置
2. properties 配置
可外部配置且动态替换。
例如:在resource资源目录下配置config.properties配置文件,在Mybatis.xml中配置以下。

<properties resource="config.properties"/>

也能够经过properties的子元素传递值:
<properties resource="config.properties">  
<property name="username" value="root"/>  
<property name="password" value="123"/>
</properties>
3. settings 设置
settings 是 Mybatis.xml 文件中极其重要的设置,它们会改变MyBatis的运行时行为,如开启二级缓存、开启延迟加载等。
4. typeAliases 类型别名
typeAliases只和XML配置有关,用来减小类彻底限定名的冗余。
第一种配置方法:
<typeAliases>  
<typeAlias alias="User" type="com.shiyanlou.mybatis.model.User"/>  
</typeAliases>
这里将全路径的com.shiyanlou.mybatis.model.User(User是包com.shiyanlou.mybatis.mode下的方法)起一个别名User,在映射文件中parameterType和resultType就能够直接使用别名User,无需使用全路径。

第二种配置方法:
<typeAliases>  
<package name="com.shiyanlou.mybatis.model" />  
</typeAliases>
指定一个包名起别名,MyBatis 会在包名下搜索须要的JavaBean,将Java类的类名做为类的类别名。
5. typeHandlers 类型处理器
typeHandlers的做用是实现JDBC类型和Java类型之间的转换,MyBatis中默认的类型处理器基本能知足平常需求。
6. objectFactory 对象工厂
7. plugins 插件
8. environments 环境
MyBatis 的环境配置实际是数据源的配置,MyBatis能够配置多个环境,帮助你将SQL映射对应到多种数据库。

注意:
尽管能够配置多个环境,每一个SqlSessionFactory实例只能对应一个数据库,有几个数据库就须要建立几个SqlSessionFactory实例。

接收环境配置的两个方法:
SqlSessionFactory sqlSessionFactory = new     SqlSessionFactoryBuilder().build(reader, environment);  
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, environment,properties);

若是忽略了环境参数,默认环境将会被加载:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader,properties);
9. transactionManager:事务管理器
MyBatis中有两种事务管理器,即 type=”\[JDBC | MANAGED\]”;

JDBC:直接使用JDBC的提交和回滚设置。

MANAGED:让容器来管理事务的整个生命周期。
10. dataSource :数据源
dataSource元素使用标准的JDBC数据源接口来配置JDBC链接对象的资源。

MyBatis 三种内建的数据源类型,即type=”\[UNPOOLED | POOLED | JNDI\]”;
1.  UNPOOLED :不支持JDBC数据源链接池,实现的只是每次被请求时打开和关闭链接。属性有:
    1)driver :JDBC驱动的Java类的彻底限定名,如 MySQL 的com.mysql.jdbc.Driver
    2)url :数据库的JDBC URL地址。
    3)username :数据库的用户名。
    4)password :数据库的密码。
    5)defaultTransactionIsolationLevel :默认的链接事务隔离级别。

2.  POOLED :支持JDBC数据源链接池,利用“池”的概念将JDBC链接对象组织起来,避免了建立新的链接实例时所必须的初始化和认证时间。

3.  JNDI :支持外部数据源链接池,它的实现是为了能在如EJB或应用服务器这类容器中使用。
11. databaseIdProvider 数据库厂商标识
12. mappers 映射器
mappers 映射器用于引用已经定义好的映射文件,告诉MyBatis 去哪寻找映射SQL的语句。

常见的方法有:
1)经过resource加载单个映射文件
<mappers>
<mapper resource="com/shiyanlou/mybatis/mapper/UserMapper.xml"/> 
</mappers>

2)经过彻底限定资源定位符(绝对路径前加上 “file:///” )加载单个映射文件。
<mappers>  
<mapper url="file:///home/project/MyBatisTest/src/com/shiyanlou/mybatis/mapper/UserMapper.xml"/>  
</mappers>

3) 经过mapper接口对象加载单个映射文件。
<mappers>  
<mapper class="com.shiyanlou.mybatis.mapper.UserMapper"/>  
</mappers>

4)  经过mapper接口包加载整个包的映射文件。
<mappers>  
<package name="com.shiyanlou.mybatis.mapper" />  
</mappers>

如下是一个简单的 MyBatis.xml 的配置文件:

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE configuration PUBLIC "-[//mybatis.org//DTD](//mybatis.org//DTD) Config 3.0//EN" "[http://mybatis.org/dtd/mybatis-3-config.dtd](http://mybatis.org/dtd/mybatis-3-config.dtd)">
<configuration>
    <!-- 为 JavaBean 起类别名 -->
    <typeAliases>
    <!-- 指定一个包名起别名,将包内的 Java 类的类名做为类的类别名 -->
    <package name="com.springMybatis.demo" />
    </typeAliases>

    <!-- 配置 mybatis 运行环境 -->
    <environments default="development">
    <environment id="development">
    <!-- type="JDBC" 表明直接使用 JDBC 的提交和回滚设置 -->
    <transactionManager type="JDBC" />
    <!-- POOLED 表示支持 JDBC 数据源链接池 -->
    <!\-\- 数据库链接池,由 Mybatis 管理,数据库名是 mybatis,MySQL 用户名 root,密码为空 -->
    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /
        <property name="username" value="root" />
        <property name="password" value="数据库密码" />
    </dataSource>
</environment>
</environments>

<mappers>
<!-- 经过 mapper 接口包加载整个包的映射文件 -->
<package name="cn.dbOperation.demo" />
</mappers>

</configuration>

MyBatis 映射文件:

映射文件是全部SQL语句放置的地方,写好SQL语句映射文件后,须要在mybatis.xml配置文件的mappers标签中引用。

映射文件包含的顶级元素:

1.  cache :给定命名空间的缓存配置。
2.  cache-ref :其余命名空间缓存配置的引用。
3.  resultMap :描述如何从数据库结果集中来加载对象。
4.  sql :可被其它语句引用的可重用语句块。
5.  insert :映射插入语句。
6.  updata :映射更新语句。
7.  delete :映射删除语句。
8.  select :映射查询语句。

resultMap:

在映射文件中也是最复杂最强大的,resultMap的设计就是简单语句不须要明确的结果映射,而不少复杂语句确实须要描述它们的关系。
resultMap的子元素包括:
1.  constructor :用来将结果注入到一个实例化好的类的构造方法中。
2.  idArg :ID参数,标记结果做为ID。
3.  arg :注入到构造方法的一个普通结果。
4.  id :一个ID结果,标记结果做为ID。
5.  result :注入到字段或JavaBean属性的普通结果。
6.  association :复杂的类型关联,多个结果合成的类型。
7.  collection :复杂类型的集,也能够引用一个外部结果映射。
8.  discriminator :使用结果值来决定使用哪一个结果集。
9.  case :基本一些值的结果映射。
resultMap的属性包括:
1.  id :当前命名空间中的一个惟一标识,用于标识一个resultMap
2.  type :类的全限定名,或者一个类型别名。
3.  automapping :为这个ResultMap开启或关闭自动映射,改属性会覆盖全局的属性autoMappingBehavior,默认值为:unset

动态SQL语句:

MyBatis 经常使用的动态 SQL 元素包括:
1.  if
2.  choose(when, otherwise)
3.  trim(where, set)
4.  foreach
5.  bind
if
if 在 where 子句中作简单的条件判断;
若是addres为空,则where id = #{id}。
若是 addres 不为空, 则where id = #{id} and addres = #{addres};

<select id="selectUserTest" parameterType="int" resultType="User"> 
select * from User where id = #{id} <if test="addres != null"> and addres = #{addres} </if>
</select>
choose(when, otherwise):
choose 的用法和 java 的switch相似。
按照顺序执行,当when中有条件知足时,则跳出choose,当全部when的条件都不知足时就输出otherwise的内容。

<!\-\- select id="selectUserTest" parameterType="int" resultType="User">
select * from User where id = #{id}
    <choose>
        <when test="username != null">
            and username = #{username}
        </when>
        <when test="phone != null">
            and phone = #{phone}
        </when>
        <otherwise>
            and addres = #{addres}
        </otherwise>
    </choose>
</select -->
trim(where, set):
trim 元素能够给本身包含的内容加上前缀(prefix)或加上后缀(suffix)。
也能够把包含内容的首部(prefixOverrides)或尾部(suffixOverrides)某些内容移除;

<select id="selectUserTest" parameterType="int" resultType="User">
    select * from User
    <trim prefix="where" prefixOverrides="and | or">
        <if test="id != null">
        id = #{id}
        </if>
        <if test="addres != null">
        and addres = #{addres}
        </if>
    </trim>
</select>

where 元素知道只有在一个以上的 if 条件知足的状况下才去插入 where 子句,并且可以智能地处理and和or条件;
<select id="dynamicWhereTest" resultType="User">
    select * from user
    <where>
        <if test="address != null">
        address = #{address}
        </if>
        <if test="phone != null">
        and phone like #{phone}
        </if>
    </where>
</select>

set 元素能够被用于动态包含须要更新的列,而舍去其余的
<update id="dynamicSetTest">
    update User
    <set>
        <if test="phone != null">phone=#{phone},</if>
        <if test="address != null">address=#{address}</if>
    </set> where id=#{id}
</update>
foreach:
foreach 元素经常使用到须要对一个集合进行遍历时,在in语句查询时特别有用:
foreach元素的主要属性:
1.  item :本次迭代获取的元素;
2.  index : 当前迭代的次数;
3.  open :开始标志;
4.  separator :每次迭代之间的分隔符;
5.  close :结束标志;
6.  collection :该属性必须指定(一、单参数且为List时,值为list。 二、单参数且为array时,值为array。 三、多参数需封装成一个Map,map的key就是参数名)

<select id="selectUser" parameterType="int" resultType="User">
    select * from User where id in
    <foreach collection="list" item="item" index="index"
        open = "(" separator="," close=")">
        #{item}
        </foreach>
</select>
bind:
bind 元素能够从OGNL表达式中建立一个变量并将其绑定到上下文。

<select id="selectUser" parameterType="int" resultType="User">
    <bind name="pattern" value="'%' + _parameter.getPhone() + '%'"/>
    select * from User where phone like #{pattern}
</select>

MyBatis、JDBC、Hibernate的区别:

MyBatis也是基于JDBC的,Java与数据库操做仅能经过JDBC完成。MyBatis也要经过JDBC完成数据查询、更新这些动做。
MyBatis仅仅是在JDBC基础上作了 OO化、封装事务管理接口这些东西。
MyBatis和Hibernate都屏蔽JDBC API的底层访问细节,使咱们不用跟JDBC API打交道就能够访问数据库。
可是,Hibernate是全自动的ORM映射工具,能够自动生成SQL语句。
MyBatis须要在xml配置文件中写SQL语句。
由于Hibernate是自动生成SQL语句的,在写复杂查询时,Hibernate实现比MyBatis复杂的多。
相关文章
相关标签/搜索