MyBatis整合

MyBatis是一款优秀的持久层框架,支持自定义SQL、存储过程和高级映射。文章详细介绍了MyBatis的配置解析,包括事务管理器、环境配置、日志工厂等,还讨论了ResultMap结果集映射、分页处理、动态SQL的使用以及MyBatis的一级和二级缓存机制。
摘要由CSDN通过智能技术生成

mybatis

1.简介

  • MyBatis 是一款优秀的持久层框架,

  • 它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis。2013年11月迁移到Github

2. 配置解析

影响mybatis的行为和属性信息

2.1事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚功能,它依赖从数据源获得的连接来管理事务作用域。默认情况下,为了与某些驱动程序兼容,它在关闭连接时启用自动提交。然而,对于某些驱动程序来说,启用自动提交不仅是不必要的,而且是一个代价高昂的操作。因此,从 3.5.10 版本开始,你可以通过将 “skipSetAutoCommitOnClose” 属性设置为 “true” 来跳过这个步骤。例如:

    <transactionManager type="JDBC">
      <property name="skipSetAutoCommitOnClose" value="true"/>
    </transactionManager>
    
  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:

    <transactionManager type="MANAGED">
      <property name="closeConnection" value="false"/>
    </transactionManager>
    

    如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

2.2 环境配置(environments)
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai&amp;useUnicode=true&amp;useSSL=true"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
</environments>
2.3 POOLED

POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

2.4 别名(typeAliases)
<typeAliases>
<!--        实体类较少-->
        <typeAlias alias="User" type="com.Tsing.pojo.User"/>
<!--        实体类较多-->
        <package name="com.Tsing.dao"/>
</typeAliases>

前者可以自定义别名

后者可以在实体类上添加注解 @Alias("别名")

2.5 映射器(mappers)

MapperRegistry: 注册绑定我们创建的mapper

第一种:通过 resoure注册

<mappers>
        <mapper resource="com/Tsing/dao/UserDaoMapper.xml"/>
</mappers>
  • / 来分割

第二种:通过 class注册

<mappers>
         <mapper class="com.Tsing.dao.UserDaoMapper"/>
</mappers>
  • 接口和配置文件必须同名
  • 且在同一个包下

第二种:通过 package注册

<mappers>
         <package name="com.Tsing.dao"/>
</mappers>
  • 同上
SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行也绝不能将 SqlSession 实例的引用放在 任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要

3.ResultMap结果集映射

resultMap

<mapper namespace="com.Tsing.dao.UserDao">
    <resultMap id="UserMap" type="User">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>

    <select id="getUserList" resultMap="UserMap">
        SELECT * FROM `user`
    </select>
</mapper>
  • resultMap=“UserMap”
  • column = 字段名;property:属性名

4.日志(Logger)

日志工厂

Mybatis日志工厂是基于接口/配置文件的源文件来代替以往的debug模式,提高排查效率.

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging
Log4j

简介

  • Log4j是Apache的一个开源项目
  • 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件…
  • 我们也可以控制每一条日志的输出格式;
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

使用

  1. 导包

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    
  2. 配置文件编写

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
    log4j.rootLogger=DEBUG,console,file
    
    #控制台输出的相关设置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #文件输出的相关设置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/Tsing.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #日志输出级别
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    
  3. setting 日志实现

    <settings>
      <setting name="logImpl" value="LOG4J"/>
    </settings>
    
  4. 测试 Log4j

    static Logger logger = Logger.getLogger(MyTest.class);
    
    @Test
    public void testLog4j(){
      logger.info("info");
      logger.debug("debug");
      logger.error("error");
    }
    

5. 分页

将大量的数据分页显示

利用MySQL中的 limit 分页查询

6.利用注解开发

底层实现机制: 动态代理

本质: 主要利用反射实现

~注解CRUD

@Param()注解

  • 基本数据类型或String类型需加
  • 引用类型不用加
  • SQL中引用的是Param()中的设定的属性名
~#{ } ${ }

#{} 解析时会加上“ ” , 而${} 直接转为字符串

#{} 可以很大程度上摆脱sql注入问题

${} 一般不能防止注入

7. mybatis 执行流程剖析

Mybatis执行流程剖析

  • Resources获取加载全局配置文件

  • 实例化SqlSessionFactoryBuilder构造器

  • 解析配置文件流XMLConfigBuilder

  • Configuration所有的配置信息

  • SqlSessionFactory实例化

  • transactional实务管理器—

  • 创建executor执行器

  • 创建sqlsession

  • 实现CRUD—

  • —<查看是否执行成功 >

  • 提交事务

  • 关闭

8. 多对一处理

将查出来的结果做结果集映射

<!--
    思路:
        1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
        2. 对查询出来的操作做结果集映射
            1. 集合的话,使用collection!
                JavaType和ofType都是用来指定对象类型的
                JavaType是用来指定pojo中属性的类型
                ofType指定的是映射到list集合属性中pojo的类型。
    -->
<select id="getTeacher" resultMap="TeacherStudent">
  select s.id sid, s.name sname , t.name tname, t.id tid
  from student s,teacher t
  where s.tid = t.id and t.id=#{tid}
</select>

<resultMap id="TeacherStudent" type="Teacher">
  <result  property="name" column="tname"/>
  <collection property="students" ofType="Student">
    <result property="id" column="sid" />
    <result property="name" column="sname" />
    <result property="tid" column="tid" />
  </collection>
</resultMap>

9. 动态 SQL

mybatis – 动态 SQL

通俗: 根据不同的条件生成不同的sql语句

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if (简单)
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
<!--choose when 类似与   switch   -->
<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG WHERE where id = #{id}
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null ">
      AND author like #{author}
    </when>
    <otherwise>
      AND views = 999
    </otherwise>
  </choose>
</select>
<!--  where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除-->
<!-- if -->
<select id="queryBlogIf" parameterType="map" resultMap="BlogMap">
  select * from mybatis.`blog`
  <where>
    <if test="title != null">
      and title = #{title}
    </if>
    <if test="author != null">
      and author = #{author}
    </if>
  </where>
</select>
<!--  set  元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。-->
  <select id="updateBlog" parameterType="map" resultType="Blog">
      update mybatis.`blog`
    <set>
      <if test="title != null">
         title = #{title},
      </if>
      <if test="author != null">
         author = #{author}
      </if>
      where id = #{id}
    </set>
  </select>
Foreach

sql 片段: 实现代码复用功能

<sql id="sql">
  <if test="title != null">
    title = #{title},
  </if>
  <if test="author != null">
    author = #{author}
  </if>
</sql>

<include refid="sql"/>
  • 最好基于单表查询来定义
  • 尽量只包含 if语句
<select id="selectBlogForeach" resultMap="BlogMap" parameterType="map">
  SELECT * FROM BLOG
  <where>
    <foreach collection="ids" item="id" open="and (" close=")" separator="or">
      id = #{id}
    </foreach>
  </where>
</select>

说白了就是拼接 SQL 语句

10. 缓存

  • 临时存储在内存
  • 使用缓存, 减少与数据库的交互次数, 减小开销, 提高效率
  • 经常查询, 插入很少

maybatis 支持两级缓存 : 一级缓存/二级缓存(全局缓存)

一级: SqlSession级别的

  • 默认开启, 且不能关闭,就是从拿到连接到关闭连接

二级: namespace级别的

  • 创建了FIFO缓存,每隔60秒刷新一次
  • 一级缓存失效之后, 缓存内容保存到二级缓存中
一级缓存

缓存失效的情况:

  • 查询不同的东西
  • 增删改
  • clearCache
二级缓存
  • 二级缓存因为是跨sqlSession的,会存在严重的脏读问题
  • 二级缓存的弊大于利,一般是设置为关闭二级缓存
  • 实际开发中,会使用第三方来缓存,比如redis

步骤:

  1. 显示开启缓存

    <setting name="cacheEnable" value="true"/>
    
  2. 使用缓存

    <!--    使用二级缓存-->
    <cache
           eviction="FIFO"
           flushInterval="60000"
           size="512"
           readOnly="true"/>
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值