MyBatis框架

MyBatis框架开发流程

此处引用MyBatis 框架工作流程
MyBatis的准备流程

MyBatis的主配置xml文件
通过读取xml文件到输入流InputStream中
通过jdk的DocumentBuilder解析InputStream,得到封装了xml的Document
将Document封装到XPathParser中
将XPathParser封装到XMLConfigBuilder中,初始化Configuration
利用XMLConfigBuilder将XML的所有内容封装到Configuration对象中,Configuration是XML配置最终的操作类
将Configuration封装到SqlSessionFactory中,SqlSessionFactory是创建SqlSession的工厂
SqlSession是最终操作数据库的类,SqlSession封装了Configuration、Executor,Executor是SqlSession最终操作数据库委派的类

生成Mapper代理类过程

sqlSession.getMapper(TestCodeMapper.class)
SqlSession中封装了Configuration,委派给Configuration去操作
获取Configuration中封装的MapperRegistry(MapperRegistry注册了所有的mapper接口对应生成代理类的MapperProxyFactory)
MapperRegistry中有一个map结构的成员变量,key为Mapper的Class ,value为MapperProxyFactory,根据class的key获取MapperProxyFactor y对象
利用MapperProxyFactory构造出MapperProxy,也就是jdk代理的最终InvocationHandler的实现类
利用jdk的动态代理方法生成Mapper最终的代理类

代理类执行sql过程

通过获取到Mapper的对象(这里实际是代理类),调用想要操作的方法
执行实现的invoke方法,将invoke传递的method参数以及Configuration等其他参数封装成MapperMethod
调用excute方法,进行逻辑的执行,根据MapperMethod封装的不同类型的方法(CRUD)调用sqlSession不同的方法
sqlSession最终委托给CachingExecutor执行
判断是否存在缓存,如果存在缓存,则委托给TransactionalCacheManager从缓存中获取结果,如果不存在缓存,则委托给SimpleExecutor执行
通过configuration提供的方法获取StatementHandler,委托给StatementHandle r执行,封装PreparedStatement,最后执行需要
委托给PreparedStatement去执行
最终交给jdk的PreparedStatement执行

MyBatis中的SqlSessionFactory创建过程

此处引用SqlSessionFactory构建过程

SqlSessionFactory 是MyBatis的核心类之一, 其最重要的功能就是提供创建MyBatis的核心接口SqlSession,所以我们要先创建SqlSessionFactory,它是通过Builder(建造者)模式来创建的,所以在Mybatis中提供了SqlSessionFactoryBuilder类。其构建分为两步

  1. 第 1 步: 通过 org.apache.ibatis.builder.xml.XMLConfigBuilder 解析配置的XML文件,读出所配置的参数,并将读取的内容存入org.apache.ibatis.session.Configuration类对象中。而Configuration采用的是单例模式,几乎所有的 MyBatis 配置内容都会存放在这个单例对象中,以便后续将这些内容读出。
  2. 第2步:使用Confinguration对象去创建SqlSessionFactory。MyBatis 中的 SqlSessionFactory 是一个接口,而不是一个实现类,为此MyBatis提供了一个默认的实现类org.apache.ibatis.session.defaults.DefaultSqlSessionFactory。在大部分情况下都没有必要自己去创建新的SqlSessionFactory 实现类,而是由系统创建。

  这种创建的方式就是一种 Builder 模式,对于复杂的对象而言,使用构造参数很难实现。这时使用一个类(比如 Configuration)作为统领,一步步地构建所需的内容,然后通过它去创建最终的对象(比如 SqlSessionFactory),这样每一步都会很清晰,这种方式值得大家学习,并且在工作中使用。

//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 来创建sqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

延申

SqlSession创建方式

SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说,当你选择其中一个方法时,你需要考虑以下几点:

  • 事务处理:你希望在 session 作用域中使用事务作用域,还是使用自动提交(auto-commit)?(对很多数据库和/或 JDBC 驱动来说,等同于关闭事务支持)
  • 数据库连接:你希望 MyBatis 帮你从已配置的数据源获取连接,还是使用自己提供的连接?
  • 语句执行:你希望 MyBatis 复用 PreparedStatement 和/或批量更新语句(包括插入语句和删除语句)吗?

  基于以上需求,有下列已重载的多个 openSession() 方法供使用

SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();

  默认的 openSession() 方法没有参数,它会创建具备如下特性的 SqlSession:

  • 事务作用域将会开启(也就是不自动提交)。
  • 将由当前环境配置的 DataSource 实例中获取 Connection 对象。
  • 事务隔离级别将会使用驱动或数据源的默认设置。
  • 预处理语句不会被复用,也不会批量处理更新。

  相信你已经能从方法签名中知道这些方法的区别。向 autoCommit 可选参数传递 true 值即可开启自动提交功能。若要使用自己的 Connection 实例,传递一个 Connection 实例给 connection 参数即可。注意,我们没有提供同时设置 Connection 和 autoCommit 的方法,这是因为 MyBatis 会依据传入的 Connection 来决定是否启用 autoCommit。对于事务隔离级别,MyBatis 使用了一个 Java 枚举包装器来表示,称为 TransactionIsolationLevel,事务隔离级别支持 JDBC 的五个隔离级别(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE),并且与预期的行为一致。

  你可能对 ExecutorType 参数感到陌生。这个枚举类型定义了三个值:

  • ExecutorType.SIMPLE:该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句。
  • ExecutorType.REUSE:该类型的执行器会复用预处理语句。
  • ExecutorType.BATCH:该类型的执行器会批量执行所有更新语句,如果 SELECT 在多个更新中间执行,将在必要时将多条更新语句分隔开来,以方便理解。

在 SqlSessionFactory 中还有一个方法我们没有提及,就是 getConfiguration()。这个方法会返回一个 Configuration 实例,你可以在运行时使用它来检查 MyBatis 的配置
如果你使用过 MyBatis 的旧版本,可能还记得 session、事务和批量操作是相互独立的。在新版本中则不是这样。上述三者都包含在 session 作用域内。你不必分别处理事务或批量操作就能得到想要的全部效果

Mapper接口的动态代理要求

  1. 映射文件的mapper.xml的名字要与mapper接口名字一致
  2. 映射文件的namespace要和mapper接口全路径一致
  3. 映射文件的statemment的id要和接口的方法名一致
  4. 映射文件的输入参数类型parameterType要和接口的参数类型《泛型》一致
  5. 映射文件的输出结果类型要和接口的返回类型一致

XML配置文件中的动态SQL标签

sql&include
此处引用sql和include标签

sql标签中id属性对应include标签中的refid属性。通过include标签将sql片段和原sql片段进行拼接成一个完整的sql语句进行执行

<sql id="sqlid">
    res_type_id,res_type
</sql>

<select id="selectbyId" resultType="com.property.vo.PubResTypeVO">
    select
    <include refid="sqlid"/>
    from pub_res_type
</select>
#引用同一个xml中的sql片段
<include refid="sqlid"/>
#引用公用的sql片段
<include refid="namespace.sqlid"/>
#include标签中也可以用property标签,用以指定自定义属性。在sql标签中通过${}取出对应的属性值。

<select id="queryPubResType" parameterType="com.property.vo.PubResTypeVO" resultMap="PubResTypeList">
    select  a.res_type_id,
    <include refid="com.common.dao.FunctionDao.SF_GET_LNG_RES_TYPE">
        <property name="AI_RES_TYPE_ID" value="a.res_type_id"/>
        <property name="lng" value="#{lngId}"/>
        <property name="female" value="'女'"/>
    </include> as res_type
    from    pub_res_type a
</select>

if

使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:

<select id="findActiveBlogWithTitleLike" resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

Where

用于处理where关键字和and

<!--where标签  作用 会自动的添加where关键字  并且会自动去除第一个and-->
<select id="selectMore2" resultType="flower">
    select *  from   flower
    <where>
        <if test="param1!=null and param1!=''">
          name=#{param1}
        </if>
        <if test="param2!=null and param2!=''">
            and  production=#{param2}
        </if>
    </where>
</select>

Choose

前面的when条件成立 后面的 when就不再判断了

<!--choose 相当于   if(){}else if(){} else if(){}..else{}-->
<select id="selectMore3" resultType="flower">
     select *  from   flower
     <where>
          <choose>
              <when test="param1!=null and param1!=''">
                  name  =#{param1}
              </when>
              <when test="param2!=null and param2!=''">
                  and  production  =#{param2}
              </when>
              <otherwise>
                  1=1
              </otherwise>
          </choose>
     </where>
</select>

set

<!--set标签  1、会自动增加set关键字  2、会去掉最后一个 逗号(,)-->
<update id="update">
    update   flower
   <set>
       <if test="name!=null and name!=''">
           name=#{name},
       </if>
       <if test="production!=null and production!=''">
           production=#{production}
       </if>
   </set>
    where id=#{id}
</update>

Trim

<!--
   trim标签
    prefix:增加前缀
    prefixOverrides:去掉指定前缀
    suffix:增加后缀
    suffixOverrides:去掉指定后缀
-->
<update id="update2">
    update   flower
    <trim prefix="set"   suffixOverrides=",">
        <if test="name!=null and name!=''">
            name=#{name},
        </if>
        <if test="production!=null and production!=''">
            production=#{production}
        </if>
    </trim>
    where id=#{id}
</update>

Foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

SqlSession中执行SQL语句的执行器Executor类型

此处引用JDBC系列

Mybatis 提供了三个 sql 执行器,即 SIMPLE(简单执行器)、 REUSE(可重用执行器)和 BATCH(批处理执行器)
SIMPLE 特点是每次执行完毕后都会将创建出来的statement关闭掉,他也是默认的执行器类型
REUSE在它在本地维护了一个容器,用来存放针对每条sql创建出来的statement,下次执行相同的sql时,会先检查容器中是否存在相同的sql,如果存在就使用现成的,不再重复获取
BATCH 特点是进行批量修改,她会将修改操作记录在本地,等待程序触发提交事务,或者是触发下一次查询时,批量执行修改

MyBatis底层封装的是JDBC,MyBatis框架单独使用的时候默认事务管理方式是什么

MyBatis单独使用时,使用SqlSession来处理事务

MyBatis的事务管理分为两种形式:

  1. 使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等。
  2. 使用MANAGED的事务管理机制:这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

week@eight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值