MyBatis

Mybatis

MyBatis中文网

mybatis – MyBatis 3 | 简介

MyBatis最初是Apache的一个开源项目IBatis

2010年迁移到了Google Code,并且在iBatis3.x版本时正式更名为MyBatis,2013年迁移到Githubs

在Mybatis使用过程中,如果导包iBatis也属于正常现象


持久性框架对比

JDBC:

  • SQL夹杂在Java代码中,耦合度高,导致硬编码内伤
  • 维护不易且实际开发需求中SQL有变化,修改源码的情况多见
  • 代码冗长,开发效率低

Hibernate和JPA:

  • 操作简单,开发效率高
  • 程序中长难复杂的SQL需要绕过框架
  • 内部自动生成的SQL,不容易做特殊优化
  • 基于全映射的全自动框架,大量字段的POJO部分进行映射比较困难
  • 反射操作太多,导致数据库性能下降

MyBatis:

  • 轻量级,性能出色
  • SQL和Java编码分开,功能边界清晰(Java代码专注于业务,SQL语句服务于数据)
  • 开发效率稍逊色于Hibernate,但是能接受

开发效率: Hibernate > Mybatis > JDBC

运行效率:JDBC > Mybatis >Hibernate


Mapper接口&MapperXML文件

对比于之前学习的JDBC使用方式,MyBatis自带连接池,需要导入的依赖如下

  • mybatis:MyBatis使用的核心依赖
  • mysql:MySQL数据库的驱动依赖

在使用JDBC时,我们对数据库的操作是使用Dao和DaoImpl

在MyBatis中,对数据库操作使用Mapper和MapperXMl

其中,Mapper接口中不再有SQL语句,而是对数据库操作的功能方法,而MapperXML专门用来写SQL语句

在com.xiaobai下新建软件包名为mapper,用以存放Mapper接口

在resources下建立目录名为mappers,用以存放MapperXML文件


mybatis-config.xml

MyBatis不需要使用连接池,因为他自己内置了连接池

那么就需要为MyBatis配置一些参数(例如JDBC四大件)

以下代码是由尚硅谷提供的原生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">
<configuration>

    <!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 -->
    <environments default="development">
        <!-- environment表示配置Mybatis的一个具体的环境 -->
        <environment id="development">
            <!-- Mybatis的内置的事务管理器 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源 -->
            <dataSource type="POOLED">
                <!-- 建立数据库连接的具体信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- Mapper注册:指定Mybatis映射文件的具体位置 -->
        <!-- mapper标签:配置一个具体的Mapper映射文件 -->
        <!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 -->
        <!-- 对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 -->
        <mapper resource="mappers/EmployeeMapper.xml"/>
    </mappers>

</configuration>

MyBatis原生调用

在之前原生JDBC的学习中,我们最后通过Dao调用JDBC的的过程是:

DAO -> BaseDao -> JDBCUtil

其实使用起来也是比较麻烦,只是两个工具类为我们封装好了对象和方法而已

后来学习了JDBCTemplate,才简化了这两个类和对JDBC的操作

原生的MyBatis在调用起来也是一样的麻烦,但后面由SpringIoC接管后,这个过程就会被简化

public class MybatisTest {
    @Test
    public void test() throws IOException {
        // 使用流读取外部配置文件(mybatis-config.xml)
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        
        // 创建sqlSessionFactory 这个对象是带有配置的模板,全局唯一
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        
        // 使用sqlSessionFactory创建sqlSession 每个业务创建一个sqlSession,相当一次会话,用完释放
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        // 获取接口的代理对象,这个接口没有具体的实现类,他代理的是Mapper接口的方法+mapperXMl中的sql语句
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = mapper.queryById(1);
        System.out.println("employee = " + employee);
        
        // 提交事务(非DQL)和释放资源
        sqlSession.close();
    }
}

注:mybatis在配置中是针对非查询开启事务的,所以在执行非查询的时候要提交事务

事务管理器

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

<transactionManager type="JDBC">
  <property name="skipSetAutoCommitOnClose" value="true"/>
</transactionManager>

iBatis

与MyBatis不同,iBatis没有Mapper接口

在调用iBatis时,不使用代理模式,sqlSession对象提供了增删改查方法,由此对象直接调用标签中的sql语句完成增删改查

sqlSession在调用增删改查的方法时,将mapper标签的namespace + crud标签的id值作为参数传递进去

缺点:

  • 传入的标签定位参数是一个字符串,没有报错提示,容易写错
  • sql的参数需要整合,每次只能传递一个参数
  • 返回值类型为Object,需要强制转型

执行逻辑

iBatis将MapperXML文件中的sql语句,存成类似键值对的形式

键:mapper标签的namespace + crud标签的id值 ,值:sql语句

mybatis-config.xml,配置好四大件之后将数据库信息缓存,同时将mapper.xml的sql语句(键值对缓存起来)

调用iBatis时,通过配置文件读取到四大件和sql,创建SqlSession工厂,创建SqlSession

调用SqlSession的增删改查时,就是在缓存中通过key找到value,带入对sql的参数并执行


MyBatis执行逻辑

Mybatis.png

为了解决iBatis存在的问题,多建立一个对应mapper.xml的接口

Mapper接口中的全限定类名对应mapper标签的namespace属性值

Mapper接口中的方法名对应crud标签的id值

这样,全限定类名+方法名的格式,也能找到具体的sql语句


代理技术

通过SqlSession对象调用getMapper,将接口的类对象作为参数传入

底层使用JDK动态代理,为此接口生成一个代理对象,利用反射的机制获取到接口的全类名和要执行的方法名

这个全类名和方法名拼成字符串(这也是IBatis时调用具体方法的所需参数),再去调用iBatis对应的方法

使用代理模式对接口内容进行丰富,将mapper.xml的sql内容填入其中,形成一个对象

使用对象调用接口的方法,我们发现参数类型和返回值类型早已规定好


Mybatis日志输出

mybatis – MyBatis 3 | 配置

MyBatis的中文官网为我们提供了非常完善的使用说明,其中就包括了MyBatis的配置文件(mybatis-config.xml)的标签含义

其中,settings标签可以配置 MyBatis 的运行时行为,是个极为重要的标签

<configuration>
    <settings>
        <!-- 开启MyBaits日志输出 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
……
</configuration>

在之后的学习中,我们会学习更多的settings的配置参数,让MyBatis使用起来更简单