欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis-用听得懂的话带你深入

程序员文章站 2022-06-19 21:16:05
...

文章内容输出来源:拉勾教育Java高薪训练营

Mybatis加载过程

  1. SpringBoot启动时就开始加载数据库配置文件并初始化SqlSessionFactory 并交给Spring,如下简单实现:

String resource = "mybatis/conf/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//从 XML 中构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new  SqlSessionFactoryBuilder().build(inputStream);
//获取session
SqlSession session = sqlSessionFactory.openSession();
   try {
      //获取Mapper
       BlogMapper mapper = session.getMapper(BlogMapper.class);
       Blog blog = mapper.selectBlog(1L);
       System.out.println(blog);
     } finally {
            session.close();
     }
  •  上个步骤实例化了SqlSessionFactory 已经初始化好了数据库配置信息 现在加入MyBatis依赖信息
  • <dependency>
      <groupId>org.mybatis</groupId>
         <artifactId>mybatis</artifactId>
         <version>3.5.2</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>

    在进入Mybatis之前,简单介绍下Mybatis:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。也就是说底层封装的是JDBC.Mybatis为我们做了大部分的工作。

  • 使用注解 譬如:@Select @Update @Insert @Delete 这些注解又是怎么实现的呢?

  • MyBatis-用听得懂的话带你深入

  • 由上图就可以看到当我们使用某一个注解时,就会去执行对应的方法,其实在项目启动的时候注解下的方法,方法名称,入参,返回参数都已经绑定到该class。当执行一个数据库操作时,用我们的sql然后与参数进行拼接,最终根据不同的注解执行不同的逻辑。

Mybatis是如何处理事务的

MyBatis-用听得懂的话带你深入

解析:当一个请求过来,会从数据库连接池中获取一个数据库连接,这个数据库连接与当前线程进行绑定,如果当前线程出现异常,则调用rollback() 进行回滚事务,否则提交事务,最后关闭当前数据库连接

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

  1. 使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等。
  2. 使用MANAGED的事务管理机制:这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理。
  • 一级缓存

    (1)  MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的

    (2) 同一个 SqlSession 对象, 在参数和 SQL 完全一样的情况,多次查询时会使用缓存。

    二级缓存

    (1) 二级缓存是基于 mapper文件的namespace的,也就是说多个sqlSession可以共享一个mapper中的二级缓存区域,是Application级别的缓存。

    (2) 二级缓存有全局和Mapper中的两种开关配置,默认是关闭的。

    (3) 二级缓存要求返回的模型类POJO是序列化的。

MyBatis高级应用

MyBatis真正强大的是在与它的xml映射语句,接下来由浅入深进行介绍

 <select id="selectPerson" parameterType="int" resultType="hashmap">
       SELECT * FROM PERSON WHERE ID = #{id}
  </select>
#{id}

#{id} :这就告诉 MyBatis 创建一个预处理语句参数,通过 JDBC,这样的一个参数在 SQL 中会由一个"?"来标识,并被传递到一个新的预处理语句中,就像这样

String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

 

MyBatis常用的属性以及含义:

  • Select Attributes
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
resultType 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。
useCache 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
fetchSize 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。
statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。
databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。
resultSets 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。
  • insert, update 和 delete 不同的属性得到不同结果

属性 描述
id 命名空间中的唯一标识符,可被用来代表这条语句。
parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值: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 的语句;如果带或者不带的语句都有,则不带的会被忽略。

动态sql

动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
<if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>

解释:这是一个简单的条件判断

foreach

解释:resultType:入参  list 作为一个集合 

<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>

 

  • MyBatis一对一关系映射 associaction 一个订单对应一个用户

  •  <!-- 这是resultMap -->
     <resultMap type="com.jy.entity.Orders" id="ordersAndUser">
            <id property="id" column="id"/>
            <result property="user_id" column="user_id"/>
            <!-- 这是映射 -->
            <association property="user" javaType="com.jy.entity.User">
                <id property="id" column="id" />
                <result property="username" column="username"/>
                <result property="password" column="password"/>
                <result property="realname" column="realname"/>
            </association>
        </resultMap>

    解释:property 对应的是我们实体类字段名称,column 是数据库字段,如果该字段有别名 则这个column就是别名

 

  • MyBatis一对多关系映射 collection 一个用户可以有多个订单

  • <resultMap type="com.jy.entity.User" id="UserAndOrders">
        <id property="id" column="uid"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="realname" column="realname"/>
        <collection property="orders" ofType="com.jy.entity.Orders">
            <id property="id" column="id"/>
            <result property="user_id" column="user_id"/>
        </collection>
    </resultMap>

    解释:上面代码容易出错的地方是:一对多数据映射失败。因为有两个id,所以两个column对应的id 不能相同,要区别开,看上图就是区别开的 uid 和 collecction下的 id

 总结:上面作为课程要点记录,也是我们工作中常用到的,这里简单的分析了MyBatis底层封装映射,事务处理,动态sql,清晰且简单,用你看的懂得话讲给你听。欢迎留言,不当之处给与指正,谢谢。