MyBatis小结

200 阅读8分钟

MyBatis的学习总结

学习MyBatis过程的小结

MyBatis简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

这是Apache的官方文档给的介绍,从中我们可以获得一些信息

  1. MyBatis是一款持久层的框架
  2. 几乎免除了JDBC Code以及设置参数获取结果集的工作
  3. 通过XML或注解来配置和映射原始类型接口Java POJO为数据库中的记录

其中前期我们能够直观的感受到的就是第二点和第三点给我们带来的遍历,试想一下我们以前在学习过程中练习的JDBC,通常要写数据库的连接,再拿着连接去创建Statement再得到结果集最后从结果集中挨个遍历数据,期间要最麻烦的就属设置参数和接收参数了,几个字段名还好,一旦字段名多了、表多了就不想写JDBC了,那么在前期学习MyBatis的时候我们就可以体验到这个框架给我们带来的一些便利。

MyBatis的框架环境搭建及环境介绍

在学习之前我们需要下载MyBatis:github.com/mybatis/myb… ,推荐下载最新版本后退4个小版本的(懂得都懂哈),保证咱们学习都能百度到答案,下载之后,打开文件夹,我们可以看到第一个jar包: 20210417174053 核心包:mybatis-3-5-2.jar,单单核心包还不够,还需要依赖包,在lib下的所有jar包,以及MySQL的jar包

20210418100647 将上面所述的jar包导入项目之后,那么前期MyBatis的框架环境搭建的准备工作就完成了(如果要使用日志的话还需要自行下载log4j的依赖包)接下来进入项目中的环境搭建

MyBatis项目环境搭建

新建项目MyBatis1将项目src分层为entitymappertest,首先我们创建一个JavaBean文件Accountentity目录中: 20210418151727 这个写过JDBC的童鞋都知道有啥用,接下来就是准备咱们MyBatis的环境了 在src根路径下创建mybatis-config.xml

<?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>
    <!--  一开始会报错
  The content of element type "configuration" must match
  "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
    意思是 "configuration"标签内的标签必须以以下标签的先后顺序进行书写
    properties
    settings
    typeAliases
    typeHandlers
    objectFactory
    objectWrapperFactory
    reflectorFactory
    plugins
    environments
    databaseIdProvider
    mappers
    可以看到properties标签必须放在第一个
  -->
    <!-- 可以在外部进行配置,并可以进行动态替换,这里用来读取jdbc.properties的JDBC连接参数 -->
    <properties resource="jdbc.properties"/>
    <!-- 数据库环境 -->
    <!--  给实体类配置别名  -->
    <typeAliases>
        <!-- 给实体类配置别名,适用于实体类较少 -->
        <!--        <typeAlias type="com.lyl.mybatis.entity.Account" alias="a"/>-->
        <!-- 实体类多时可以直接设置包别名,返回类型直接写类名即可,一般小写,推荐写这种形式 -->
        <package name="com.lyl.mybatis.entity"/>
    </typeAliases>
    <!--............................................................-->
    <environments default="MySQL">
        <environment id="MySQL">
            <!-- MyBatis中的事务管理 下面制指定了和JDBC一样 -->
            <transactionManager type="JDBC"/>
            <!-- 底层采用连接池原理 -->
            <dataSource type="POOLED">
                <!--       读取jdbc.properties中的配置信息         -->
                <property name="driver" value="${m_driver}"/>
                <property name="url" value="${m_url}"/>
                <property name="username" value="${m_user}"/>
                <property name="password" value="${m_pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!--............................................................-->
    <!-- 扫描映射文件 -->
    <mappers>
        <mapper resource="com/lyl/mybatis/mapper/Account.xml"/>
    </mappers>
</configuration>

上面代码的注释可以选择性看,其实我们手动写的mybatis-config.xml文件是MyBatis的核心配置文件,查看API我们可以知晓在Java Code中使用Mybatis需要构建 SqlSessionFactory顾名思义是专门创建SQL会话的工厂,可以看作是生产程序与数据库直接连接实例的工厂,那么我们具体操作核心肯定是围绕着SqlSessionFactory里面的东西来实现的,后面会提到。 那么写了MyBatis的核心配置还不行,数据库连接之后那增删改查操作的sql语句在哪呢?是不是直接卸载mybatis-config.xml里面呢?上面代码的最后可以看到有<mappers>标签,这个标签用来扫描映射文件,直接查看API的XML映射文件的介绍:

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

ok,这下我们知道映射文件其实就是编写咱们sql代码的文件,而mybatis-config.xml中的<mappers>标签就是用来扫描映射文件映射器,让MaBatis知道去哪寻找SQL映射语句,那么我们接下来是在mapper目录下编写映射文件AccountMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespance="com.lyl.mybatis.mapper.Account">
<!-- namespance:命名空间,用于在java代码中找到正确的SQL映射语句 -->

<!-- public Account listAccount(){} -->
    <select id="listAccount" resultType="account">
      select * from account
    </select>
</mapper>

Account.xml写一个简单的查询,具体标签作用可以看官方API,将上面<select>标签翻译成Java Code就是public Account listAccount(){},这下就清楚明了了id和resultType的作用了,那么到此MyBatis项目的基本环境搭建就完成了,那么做一个小结:

  1. 导入核心包、依赖包、数据库核心包,将项目分层,并创建好JavaBean
  2. 编写MyBatis的核心配置mybatis-config.xml
  3. 编写SQL映射文件AccountMapper.xml

在编写配置文件的时候,我们会编写很多配置信息,这里可能显得MyBatis的优势不足,这与我们平常写的JDBC没什么区别,代码量看似也没有减少,那么接下来我们就从测试中感受一下MyBatis的便利,同时一定不要被配置文件搞得头昏眼花,记住根本的三步骤就好了

MyBatis的具体操作

在Test包下创建Test.java用来测试咱们的MyBatis,在此之前介绍一下使用MyBatis来操作数据库的核心类:

  1. SqlSessionFactoryBuilder
  2. SqlSessionFactory
  3. SqlSession

使用MyBatis的核心基础就是围绕着这三个类来实现的,SqlSessionFactoryBuilder创建SqlSessionFactorySqlSessionSqlSessionFactory中获取,具体的操作借助SqlSession实现,这样三者的关系就清楚一些了,让我们来测试前的准备:

public static void main(String[] args){
        String resource = "mybatis.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            // 1.解析mybatis.xml文件,MyBatis提供了Resources类来获取MyBatis的核心配置文件输入流
            inputStream = Resources.getResourceAsStream(resource);
            // 2.根据解析的信息得到sqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            // 3.得到Session
             sqlSession = sqlSessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (sqlSession!=null){
                sqlSession.close();
            }
        }
    }

上面是得到SqlSession的步骤,接下来执行查询方法

三种查询方式

SqlSession提供了三种查询方式便利我们进行简单的查询操作,同时也对应着三种查询结果集不一样

List

AccountMapper.xml中编写SQL语句

<select id="listAccount" resultType="account">
  select * from account
</select>

编写好后我们开始执行java代码

  List<Account> list = sqlSession.selectList("com.lyl.mybatis.mapper.Account.listAccount");
  System.out.println(list);

打印结果

[Account{id=1, username='张三', balance=1000.0}, Account{id=3, username='王五', balance=2000.0}, Account{id=4, username='赵六', balance=4000.0}, Account{id=5, username='丈八', balance=3000.0}]

看到java代码我们得知返回的结果是List,那么下面两种方式大同小异只是返回类型不一样,这里提一点,上述的AccountMapper.xml<mapper namespace="com.lyl.mybatis.mapper.Account">其中的namespace的作用就在此体现出来了,保证我们SqlSession根据namespace和每个SQL操作标签的id来映射出SQL语句并对其操作

对象

<select id="selectOne" resultType="account">
        select * from account where id=3
</select>

执行java代码

  Account account = sqlSession.selectList("com.lyl.mybatis.mapper.Account.selectOne");
  System.out.println(account);

打印结果

Account{id=3, username='王五', balance=2000.0}

Map

<select id="selectMap" resultType="map">
        select * from account
</select>

执行java代码

Map<Object, Object> account = sqlSession.selectMap("com.lyl.mapper.AccountMapper1.selectMap", "id");
System.out.println(account);

打印结果

{1={balance=1000.0, id=1, username=张三}, 3={balance=2000.0, id=3, username=王五}, 4={balance=4000.0, id=4, username=赵六}, 5={balance=3000.0, id=5, username=丈八}}

在Map中的泛型不要改!不要改!不要改!貌似改了也无所谓,最好不要更改,万一报错了我可不负责,其中Map中有两个参数传递,看结果集应该不难推断出两者关系和id参数的含义。 这三种方式之中推荐使用List,因为使用Map能做的List基本上也能做到,简单的查询也不需要使用到Map的特性,后期开发中也可能用到Map,这就需要自行理解使用了。

参数传递操作

我们的SQL语句不可能写死,需要根据我们的需求来进行指定的SQL操作,这个时候就需要传递参数,MyBatis是SQL和Java代码实现了解耦,同时也给我们对应的接口来提供参数的传递,大致分为三种传值方式。

直接传值

这个应该不太好取名,MyBatis中内置了一些Java的类型别名在API可以查到,可以通过别名简化在配置文件中的全限定类名,是一些基本数据类型和包装类。

对象传值

顾名思义就是将一个对象作为参数传入sqlSession的方法中,MyBatis在处理的时候会将对象里的值按照SQL映射文件的对应语句格式传值,这种方式在处理单表查询的确方便,但是在处理多表的时候会显得非常有局限性,一个对象不可能包含多表的所有字段,那么解决方法是什么呢? 所以我们接下来学习用Map传值。

Map传值

        Map<String,Object> map = new HashMap<>(); // 创建Map泛型规定为Key--String,Value--Object
        // 将数据压入map
        map.put("id",1);
        map.put("username","张三");
        // 传值,SQL映射文件的sql语句取值按照key来进行取值
        Account account = sqlSession.selectOne("com.lyl.mapper.AccountMapper2.selectOne3", map);

Mapper代理增删改查操作

upDate操作与查询操作同理,只是方法不同,但是同样是由SqlSession对象来操作,传入参数最多也一个,这样造成了局限性,并且,我们并没有向往常一样写数据库操作的接口,造成了后期代码可维护性低,所以开始学习Mapper代理来解决问题。