• Mybatis-lean


    一、传统JDBC 操作存在的问题

    • 原始jdbc开发存在一些问题:
      (1)数据库创建连接、释放频繁,造成系统资源的浪费,进而影响系统性能。
      (2)sql语句再代码中硬编码,造成代码不宜维护,实际应用sql变化的可能性比较大,而sql的变化需要改变java代码。
      (3)查询操作时,需要手动将结果集中封装到实体中去。插入时,需要手动将实体数据设置到sql语句的占位符位置。
    • 针对上面问题,mybatis给出了具体的解决方案。
      (1)使用数据库连接池初始化连接资源。
      (2)将sql语句抽取到xml配置文件里。
      (3)使用反射等底层技术,将实体与表进行属性与字段的自动映射。

    二、Mybatis的介绍和使用

    2.1、介绍

    在这里插入图片描述

    2.2、mybatis的快速入门

    -首先, 添加mybatis的坐标
    在这里插入图片描述

    • 其次,创建数据表。并给表里面添加一些数据。
    	create table user(
    		id int primary key auto_increment,
    		username varchar(10),
    		password varchar(10)
    	);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 编写User实体类。
      在这里插入图片描述
    • 然后编写映射文件:userMapper.xml文件。在写这个的时候需要注意的是namespace不敢忘了写,至于namespace所对的值随便写,但是一般都是按照自己的事务去命名。其次就是id属性不敢忘了写。后面调用需要用到。最后就是注意在sql标签里面参数类型,和返回值类型的书写。
    • 下图已经编写增删改查的常见操作方式。但是有些地方还是需要提一下他们的注意事项
      (1)插入操作,在映射文件中使用parameterType属性指定要插入的数据类型。
      (2)插入操作设计数据库数据的变化,所以要是有sqlSession对象显示的提交事务,即:sqlSession.commit()。
      (3)sql语句中使用#{实体属性名}方式引用实体中的属性值。
      (4)sql语句中使用#{参数名称}方式引用传递的单个参数。
      在这里插入图片描述
    • 编写核心文件SqlMapConfig.xml。在这个里面可以配置数据类型的别名、配置数据源环境、以及加载我们上一步编写的映射文件。**注意:在配置数据源的时候,我们需要用到数据在properties里面写着,因此在这里面引入了properties文件。
      在这里插入图片描述
    • 上面引入的properties配置文件。
      在这里插入图片描述
    • 最后,就是编写测试类。在编写时,按照下图的步骤,前三步一般都是一样的,主要就是到了第四步,根据SqlSession对象调用不同的方法来操作数据库。其次就是在调用的的方法里面要将自己在前面映射文件里面写的sql语句映射进来,现在知道写namespace和id的作用了吧。在使用完之后,别忘了关闭相应的流。
      在这里插入图片描述
      在这里插入图片描述
    • 到这里,快速入门就讲完了。

    2.3、mybatis的映射文件概述

    • 下面是映射文件的标注,通过下图,就可以对映射文件的大概书写就了解了。
      在这里插入图片描述

    2.4、mybatis的核心配置文件概述

    • 下图就是快速入门时编写的核心配置文件,在该文件里面一般就是用来起别名、配置数据源环境、加载映射文件、类型的转换等等。
    • 可以配置的属性有:
      (1)properties属性:加载properties文件。
      (2)typeAliases:类型别名
      (3)typeHandlers:类型处理器
      (4)plugins:插件
      (5)enviroments:环境
      (6)mappers:映射器

    2.4.1、enviroments标签的使用

    • 这个标签主要是用来配置数据库环境。
      在这里插入图片描述
    • 该标签的具体使用
      在这里插入图片描述

    2.4.2、mapper标签的使用

    • 该标签主要就是用来加载映射文件的。加载的方式一共有一下几种。
      在这里插入图片描述

    2.4.3、properties标签的使用

    • 在开发中,我们习惯于将数据源信息抽取成一个单独的properties文件,该标签就是用来将properties文件导入到核心配置文件里面。
      在这里插入图片描述

    2.4.4、typeAliases标签的使用

    • 这个标签就是用来为Java类型设置一个短名字。具体使用参考下图;
      在这里插入图片描述
    • 上图就是用来起别名,但是mybatis框架也替我们设置一些常用类型的别名。具体请看下图:
      在这里插入图片描述
      在这里插入图片描述

    2.5、mybatis的相应API

    • 在上面快速入门的测试案例中,我们是直接使用mybatis的API,下面我们来具体讲讲这写API的使用。

    2.5.1、加载文件的流对象——Resource

    • 这个不是属于mybatis的API,他是org.apache.ibatis.io包中的一个类。它主要帮我们从类路径下、文件系统、一个web URL中加载资源文件。而在这里,主要就是用来加类路径的载核心配置文件。

    2.5.2、工厂构造器SqlSessionFactoryBuilder

    • 通过使用该工厂构造器的build方法来加载核心文件的输入流从而构造一个 SqlSessionFactory对象。

    2.5.3、SqlSession实例

    • 上一步,我们通过工厂构造器创建了一个工厂对象。然后通过该工厂对象来创建一个SqlSession对象。这个实例是非常强大的一个类,我们使用SQL语句、提交事务、回滚事务和获取映射器实例的方法都要依赖与这个实例。
    • 通过工厂构造器构造该实例的方法有两种:
      (1)oppenSession():或默认开启事务,但是事务不会自动提交,也就意味着需要手动提交事务,更新操作才能持久化到数据库中。
      (2)oppenSession(boolean b):如果参数设置为true,则不需要手动提交事务。如果设置为false,就和没有参数的那个一样。
    • 它执行SQL语句的方法主要有:注意:下面的方法里面使用到的参数我没有写。
      (1)selectOne()
      (2)selectList()
      (3)insert()
      (4)update()
      (5)delete()
    • 操作事务的方法主要有:
      (1)commite()
      (2)rollback()

    三、接口代理的开发方式

    • 在上面我们讲到的快速入门案例,是利用传统的开发方式进行编写。但是在实际开发中,我们常常用到是接口代理的开发方式。下面我们就来看看,如何使用接口代理的方式进行开发。

    3.1、代理开发方式遵循的规范

    • mapper接口开发需要遵循以下规范:也可以参考下图
      (1)mapper.xml文件中namespace的值就是mapper接口的全类名。
      (2)mapper接口里面的方法名和mapper.xml文件中定义的每一个statement的id相同。
      (3)mapper接口方法的参数类型和mapper.xml文件中定义的每一个的statement的parameterType的类型相同。
      (4)mapper接口方法的返回值类型和mapper.xml文件中定义的每一个的statement的resultType的类型相同。
      在这里插入图片描述

    3.2、代理开发的实现步骤

    • 第一步:导入坐标
      和快速入门案例的一样
    • 第二步:编写核心配置文件
      和快速入门案例的一样
    • 第三步:编写User类
      和快速入门案例的一样
    • 第四步:编写UserMapper接口
      在这里插入图片描述
    • 第五步:在接口里定义方法,这里我为了节省空间就只写了两个方法。
      在这里插入图片描述
    • 第六步:编写映射文件userMapper.xml,将接口里面方法所要实现的业务sql语句写进来。注意我用红色标注的,也就是namespace的值要和mapper接口的全类名一样。id的值和方法名称一致。参数类型、返回值类型也要和方法定义的一致
      在这里插入图片描述
    • 第七步:测试,这里我就只将find这个操作的测试贴出来,另外一个和这个大同小异。注意下图的第四步
      在这里插入图片描述

    四、mybatis映射文件的深入学习

    4.1、动态sql语句

    • 根据实际的业务场景需求不一样,往往SQL语句也就不一样。但是通过上面的学习,我们应该也发现,我们常常都是直接将sql语句写死到映射文件里面。那么该如何动态的写sql语句呢?接下来我将讲解动态SQL语句的书写。

    4.1.1、动态SQL之< if >

    • 根据实体类的不同取值,使用不同的SQL语句进行查询。比如在id不为空时可以根据id查询,如果username不为空还要加入用户名作为查询条件。这种情况在多条件组合查询中经常会碰到,很明显这就需要动态SQL语句。下面我们就说说这重动态的sql语句如何写。
    • 动态SQL,是在映射文件中进行书写,在按照上面的快速入门案例或者代理接口的案例搭建好项目之后,就可以在映射文件中开始书写。通过下图,我们很容易就能看出来添加一个if标签,在test里面写上条件判断,如果条件成立,则就将if标签包裹的语句片段添加到SQL语句里面,从而达到动态书写SQL语句的效果。
      在这里插入图片描述

    4.1.2、动态SQL之< foreach >

    • 这个动态语句常常用于带有in关键字的SQL语句中。
    • 例如:select * from user where id in(1, 2, 3 )。则我们就可以按照下图去书写。猛地一看,哇偶,这是什么鬼,看不懂。其实这个你仔细看了之后就会发现这其实就是一个字符串拼接过程,他将存储在list里面的参数用逗号分隔,按照sql语句的格式一个一个的拼接起来,从而形成我们需要的sql语句。
      在这里插入图片描述
    • 写到这里,我再多说一下,动态SQL语句还有其他标签,我就不再写了,学会这两个,相信大家在学其他的也就会很简单。

    4.2、动态SQL语句的片段抽取

    • 在映射文件里面有时候在不同的statement里面会出现相同的sql语句,如果现在这些相同的SQL语句都需要同一处,那么一个一个去改不便于维护,于是就有了抽取这一想法。将这些相同的SQL语句抽取出来,然后给起个名字,然后在使用的地方将这个名字引入。以后在修改时,只需要修改提取出来的那个就行了。下面就让我们来看看这是怎么做到的。
    使用场景:
    (1)当出现重复代码时,例如下面这两个查询都出现了select * from user。那么我们
    就可以考虑将其共同部分抽取出来。
        <select id="findByCondition" resultType="user" parameterType="user">
            select * from user
            <where>
                <if test="id != 0">
                    and id = #{id}
                </if>
                <if test="username != null">
                    and username = #{username}
                </if>
                <if test="password != 0">
                    and password = #{password}
                </if>
            </where>
        </select>
    
        <select id="findByIds" resultType="user" parameterType="list">
            select * from user
            <where>
                <foreach collection="list" open="id=(" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </where>
        </select>
    
    (2)共同部分的抽取过程:将共同部分的sql语句抽取出来放到<sql></sql>标签里面,然后
    再在使用这些共同sql语句的地方配置上<include></include>标签。如下面所示。
    
    <!--    片段的抽取-->
        <sql id="selectUser">select * from user</sql>
    
        <select id="findByCondition" resultType="user" parameterType="user">
            <include refid="selectUser"></include>
            <where>
                <if test="id != 0">
                    and id = #{id}
                </if>
                <if test="username != null">
                    and username = #{username}
                </if>
                <if test="password != 0">
                    and password = #{password}
                </if>
            </where>
        </select>
    
        <select id="findByIds" resultType="user" parameterType="list">
            <include refid="selectUser"></include>
            <where>
                <foreach collection="list" open="id=(" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </where>
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    五、mybatis配置文件的深入学习

    5.1、typeHandlers标签的使用

    • 该标签是用来做类型转换的。比如,我现在将一个日期数据2022/6/26按照该格式赋值给Java类的一个属性。但是为了节省空间,在将该数据存储到数据库的时候我希望将他按照long类型的数据进行存储。所以我们就需要做类型转换,在存储的时候将字符串格式的日期转换为long类型,在读取的时候,将long类型的数据再转化为字符串格式。下面就来看看该如何做。
    • 第一步:定义一个转换类并继承BaseTypeHandler类。注意这个泛型就是需要转换的类型
      在这里插入图片描述
    • 第二步:实现该接口里面的方法,该接口里面一共有四个方法需要实现。其中第一个是用来将java里面的数据类转为数据库里面的类型,为了将数据存储到数据库中。后面三个都是用来将数据库里面的类型转为java的数据类型,为了从数据库读取出来后仍然还是Java得数据类型。具体的使用请参考下图
      在这里插入图片描述
    • 第三步:将写好的转换器配置到中心配置文件里面
      在这里插入图片描述
    • 第四步:测试
      mybatis_config项目里面有测试

    5.2、plugins标签的使用

    • mybatis可以使用第三方插件来对功能进行扩展。例如下面我们以分页助手PageHelper为例。
    • 第一步:导入PageHelper坐标
      在这里插入图片描述
    • 第二步:在核心配置文件里面进行配置插件。
      在这里插入图片描述
    • 测试
      这一部分的代码还没写,回头补上

    六、mybatis的多表操作

    6.1、一对一查询

    在这里插入图片描述

    • 我们上面的案例都是一对一的单表查询方式,所以在这一步的就不再多说什么了。

    6.2、一对多查询

    • 我们先来看一个场景。一个客户要查询自己的订单,那么就需要将该客户的所以订单都反馈给客户。而在数据库中,我们通常是将客户存到一张表里,将订单存到另一张表里。因此这个业务操作就是一个典型的多对多操作。
    • 接下来,我们首先创建一个Java类,用来存储客户和他的所以订单的类。如下图所示:注意:别忘了写这个类的get/set方法。我这里是为了节省空间,所以就没有写
      在这里插入图片描述
    • 然后,我们在mapper接口里面添加上相应的方法。
      在这里插入图片描述
    • 接着在映射类里面写上相应的SQL语句。下面写了这么多肯定就会有人看不懂了,接下来我就介绍一下这一部分都是什么意思。
    • 由于现在的场景是一对多的方式,所以在User类里面也包含一个订单类的集合,接下来我们就来看看这个order集合属性的值该如何封装。首先,prperties的值就是user类里面这个oredr集合的属性名,ofType是该集合的泛型类型,也就是order。接下来就是封装order类里面的属性,和封装user的方式一样。具体请参考下图。写到这里可能想的多的人就会问,现在里面是一个order类的集合。那如果只是一个简简单单的order类成员,那该如何对其进行封装?请看6.3部分
      在这里插入图片描述
    • 测试
      在这里插入图片描述
      在这里插入图片描述

    6.3、6.2的疑问解决

    • 在6.2篇章时,我们提到了一个问题:**如果user类里面现在只有一个简简单单的order类,那么我们该如何把从数据表查询到的有关order类里面的字段值属性封装到user类里面的order类成员的属性里面?**一共有两种方式。接下来我们就开始第一种方式的封装,注意:上面我们说的是在user类里面有一个order成员,但是下面举例的时候我写的是order里面有一个user类的成员。封装方式都是一样,希望不要混淆。
    • 第一种:这种方式其实很容易看懂,封装的时候通过类成员来点上一个它里面的属性就可以了。这个知识点在javaSE阶段就已经学习过了。有的人可能会说,你这个类里面的成员都被private修饰了,不能使用点来调用。能想到这一点很好,但是这里的配置文件语法就是这样规定的,对于规定好的东西,不要想得太多,知道怎么用就行。
      在这里插入图片描述
    • 第二种:上面我们说了通过类成员来点上他的属性值就可以了。下面我们换另外一种方式来解决这个问题。我们可以通过association这个标签来解决这个问题。这个标签里面的property的值就是类里面的成员名称,后面的javaType的值就是该成员的类型,(注意:我们这里之所以写的是user,而不是user类的全类名,原因就是因为我们在配置文件里面使用了起别名的方式)。然后,剩下的就按照正常的配置写法去写就行了。太多的废话就不说了,具体使用请参考下图
      在这里插入图片描述

    6.3、多对多查询

    在这里插入图片描述

    • 多表查询和代表查询的做法一样,都是先在mapper接口里面将需要进行多对多的业务方法定义好,然后去映射文件中编写相应的SQL语句,最后就可以使用了。

    七、注解开发

    • 之所以学习注解开发,原因是注解开发不仅可以不用写配置文件,而且注解开发慢慢的已经成为一种趋势。

    7.1、注解开发快速入门

    • 第一步:导坐标
      ** 和上面的入门案例一样**
    • 第二步:编写User类
      ** 和上面的入门案例一样**
    • 第三步:mapper接口,其实相当于写映射文件,只不过是将映射的SQL语句写到了注解里。这个接口里面主要是用注解配置了单表操作的方法,多表操作在下面在进行讲解
      在这里插入图片描述
    • 第四步:编写核心配置文档,其他的和之前都一样,唯独这一块不一样,之前这里写核心映射文件的目录结构,现在这里写mapper接口的包目录结构。
      在这里插入图片描述
    • mapper接口的目录结构。
      在这里插入图片描述
    • 测试
      在这里插入图片描述
    • 到这里,快速入门就写完了。

    7.2、mybatis常见注解的讲解

    • @Insert:往数据库里新增数据;
    • @Delete:删除数据;
    • @Update:更新数据;
    • @Select:查询数据
    • 上面这四个注解在快速入门里面都已经使用过了,相信大家应该可以看懂。接下来我们就讲讲下面这几个注解该如何去使用。首先,先让我们看看官方定义的他们的作用是什么。
    • @Result:实现结果集封装;
    • @Results:可以与@Result一起使用,封装多个结果集;
    • @One:实现一对一结构封装;
    • @Many:实现一对多结果封装;
    • 看完之后相信很多人和我一样,一脸懵逼,这是啥呀,看不懂。废话不多说,看不懂就上例子,结合例子相信很多人很快就能看懂。仔细看看这个就会发现@Results注解和我们前面学的resultMap标签很像,没错,这里的这个注解和那个标签是一个作用。那么很容易就可以看出@Result注解和result标签是一个作用。为了方便对比,我将使用配置文件的那个照片放在了下面,方便去对比。来,接着往下看,现在就到了这个@Many注解了,仔细想一下前面讲的那个一对多的案例,很容易就能想到这就是那个多。@Result注解里面的property属性的值就是那个order类集合的名称,javaType的值就是集合的类型。但是这个column的值为啥是id,想不明白。其实也不难,仔细想一下,多对多的数据表,我们通常使用一张中间表来将两张表结合起来。通过将这个id从而查询到这个user_id所对应的其他order_id,因此就可以查询到符合条件的所以order类的数据。现在我们就来说说这个id,其实这里是将这个id作为方法的一个形参传递到findById这个方法里面(这个方法的照片我也放在了下面),而这个方法就帮我们完成了那个多的查询从而返回回来。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 讲完@Many注解,可能很多小伙伴就已经懵了。说实话,我在刚刚学到这个的时候也是很懵的,但是记住了“万事开头难”。接下来我们说说@One这个注解,如果上面的那个注解都理解了,那么下面这个对你而言就是手到擒来。@One这个注解就是用于我们上面6.3那一章节所解决的那种情况。和上面一样,@Result里面的property的值就是属性名称,javaType就是该属性的类型,而这个uid就是用来查询该order对象里面的那个user对象的。具体的查询是通过selectById这个方法完成的。我将这个方法的照片也放到下面。
      在这里插入图片描述
      在这里插入图片描述
    • 到这里mybatis的基础用法就将完了,希望对大家有帮助。
  • 相关阅读:
    sd卡上移植filex
    【MySQL系列】- LIKE查询 以%开头一定会让索引失效吗
    工程效能CI/CD之流水线引擎的建设实践总结
    计算机毕业设计JAVA网上商城购物系统mybatis+源码+调试部署+系统+数据库+lw
    出现Browse information of one xxxx解决方法
    【Unity之UI编程】在Unity中如何打图集,来降低DrowCall
    【Java多线程】ThreadLocal内存泄露问题
    JAVA概述
    【本文将经常更新】代码评审中的哲学|一起来看看我们进行java代码评审后提出来的意见吧
    Postman的环境变量和全局变量
  • 原文地址:https://blog.csdn.net/qq_46111881/article/details/125470044