MyBatis源码分析-1 MyBatis基本原理

                                                                                                                                                                                                                                                                  作者:田超凡

                                                                                                                                                                                                                                                                  版权所有,严禁复制转载

 

1.MyBatis简介

   MyBatis是一个优秀的JavaEE数据持久层ORM框架,它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置带来的SQL注入风险。其主要思想是将SQL语句从程序代码中剥离出来,单独将SQL语句定义在xml配置文件中,实现SQL的灵活配置。这样做的好处是可以在不修改程序代码的情况下,直接在配置文件中修改SQL语句,降低了程序代码和SQL语句的耦合度。

 

 

2.ORM简介

  ORM指的是对象/关系映射(Object Relational Mapping),是数据持久化的一种实现方式。数据持久化指的是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。ORM在对象模型和关系型数据库之间建立了一座桥梁,通过建立Java实体类和数据库表之间的映射关系,实现使用Java代码操作实体类的属性即可操作关联的数据库表中的数据,是一种半自动化的ORM实现。基于ORM,MyBatis在对象模型和关系型数据库的表之间建立了一座桥梁,通过MyBatis建立SQL关系映射,以便捷的实现数据的存储和管理操作。

 

 

3. MyBatis环境搭建

(1) .搭建MyBatis框架环境需要用到的Jar包

log4j-1.2.16.jar

mybatis-3.2.2-sources.jar

mybatis-3.2.2.jar

mysql-connector-java-5.1.0-bin.jar

Jar包说明:

log4j-1.2.16.jar  log4j开源日志记录工具

mybatis-3.2.2.jar MyBatis核心jar包

mybatis-3.2.2-sources.jar MyBatis核心jar包的源码包

mysql-connector-java-5.1.0-bin.jar MySQL数据库驱动包

 

创建Java Web项目并将以上Jar包导入到项目的WEB-INF/lib目录下并进行BuildPath,可以根据需要导入MyBatis-source.jar这个源码包方便查看MyBatis框架API中定义的类和接口的相关信息。

 

导入MyBatis源码包方式:

Project-->Referneces Librarys-->mybatis-3.2.2.jar-->右击properties-->add attachment source-->从工作空间中选择或者从文件中的选择mybatis-3.2.2-sources.jar包-->apply save保存

 

(2).创建基本目录结构

src目录下:

创建Source Folder类型----resources目录:

database.properties 数据源配置文件

log4j.properties log4j日志配置文件

mybatis-config.xml MyBatis核心配置文件

 

dao包:存放Mapper映射器接口和SQL映射文件mapper.xml

entity包:存放实体类(pojo实体模型),需要遵循Java Bean规范

util包:存放MyBatisUtil工具类,构建MyBatis核心API实例

test包:测试类

注意:没有特殊说明,本文档总结的MyBatis框架测试都是在控制台进行,使用log4j输出日志

 

(2) .配置MyBatis核心配置文件mybatis-config.xml,基本配置项如下:

<configuration>

   <!-- 引入数据源配置文件 -->

   <properties resource="database.properties"></properties>

   

   <!-- 配置MyBatis运行时行为,Log日志实现 -->

   <settings>

     <setting name="logImpl" value="LOG4J"></setting>

   </settings>

   

   <!-- 实体类指定别名 -->

   <typeAliases>

     <typeAlias alias="Bill" type="entity.Bill"/>

     <typeAlias alias="Provider" type="entity.Provider"/>

   </typeAliases>

   

   <!-- 配置MyBatis运行时环境 -->

   <environments default="environment">

     <environment id="environment">

       <!-- 配置事务管理器 -->

       <transactionManager type="JDBC"></transactionManager>

       

       <!-- 配置数据源 -->

       <dataSource type="POOLED">

         <property name="driver" value="${driver}"></property>

         <property name="url" value="${url}"></property>

         <property name="username" value="${username}"></property>

         <property name="password" value="${password}"></property>

       </dataSource>

     </environment>

   </environments>

   

   <!-- 引入SQL映射文件 -->

   <mappers>

     <mapper resource="dao/BillMapper.xml"></mapper>

     <mapper resource="dao/ProviderMapper.xml"></mapper>

   </mappers>

</configuration>

 

基本层次结构如下:

注意:MyBatis核心配置文件配置项必须遵循以下顺序配置

Configuration 根节点,管理所有MyBatis配置项

   properties 可以引入在Java属性配置文件中配置的数据源文件(database.properties),也可以直接使用子元素property配置数据源

   settings 修改MyBatis运行时的行为方式

   typeAliases 为Java类型命名一个别名(简称)

   typeHandlers 类型处理器

   objectFactory 对象工厂

   plugins 插件

   environments 环境

       Environment 环境变量

         transactionManager 事务管理器

         dataSource 数据源

   mappers 映射器

 

配置项元素说明:

properties元素:描述外部化、可替代的属性。

(1)通过resource属性引入外部database.properties数据源配置文件

(2)通过定义子元素<property>直接配置数据源

 

settings元素:设置一些非常重要的设置选项,用于设置和改变MyBatis运行中的行为。常用配置项如下:

name属性       value属性     默认值

cacheEnabled:对在此配置文件下的所有cache进行全局性开关设置             true | false   true

lazyLoadingEnabled:全局性设置懒加载,如果设置为false,则所有相关联的都会被初始化加载,即立即加载模式  true | false   true

autoMappingBehavior:MyBatis对于resultMap的自动映射匹配级别  NONE | PARTIAL | FULL  PARTIAL

 

typeAliases元素:配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入多余的完整类名,简化操作。

子元素:typeAlias

属性:

alias 类型别名

type 完整类型限定名

子元素:package

属性:name 扫描制定包下的所有JavaBean并默认设置一个别名(默为类名)

 

environments元素:配置MyBatis多套运行环境,如开发环境、测试环境、生产环境等,可以灵活选择不同的配置,从而将SQL映射到不同的数据库环境。

注意:必须使用default属性指定默认运行环境。

子元素:

environment:MyBatis其中一套运行环境,需要指定id属性,并确保该id属性值全局唯一。

   子元素:

   transactionManager:事务管理器,设置其类型为JDBC,MyBatis有两种事务管理类型,JDBC和MANAGED.直接使用JDBC的提交和回滚功能,依赖于从数据源获得连接来管理事务的生命周期。

  dataSource:使用标准的JDBC数据源接口配置JDBC连接对象的资源。MyBatis提供了三种数据源类型(POOLED/UNPOOLED/JNDI),一般采用POOLED类型,表示使用数据库连接池的概念来管理数据库连接,有利于快速响应请求。

 

mappers:映射器,用来定义SQL映射语句,通过指定mapper子节点的resource属性引入SQL映射文件的类资源路径,如dao/UserMapper.xml

有两种方式引入SQL映射文件

(1) .类资源路径获取

<mappers>

  <mapper resource=”dao/UserMapper.xml”/>

</mappers>

(2) .使用URL获取资源

<mappers>

  <mapper =”file:///D:/dao/UserMapper.xml”/>

</mappers>

 

(3) .创建pojo模型(实体类)和dao接口(mapper映射器接口)

注意:

1.实体类必须满足JavaBean规范

2.mapper映射器接口一般与SQL映射文件同名。并且在SQL映射文件的根节点mapper的namespace属性中必须指定该SQL映射文件对应的Mapper映射器接口,并确保namespace属性值全局唯一。

3.接口中定义的方法名一般要和SQL映射文件中的元素id对应。

 

(4) 创建SQL映射文件

例:

<mapper namespace="dao.ProviderMapper">

  

  <!-- 查询供应商表总记录数 -->

  <select id="count" resultType="int">

    SELECT COUNT(*) FROM `smbms_provider`

  </select>

  

  <!-- 查询供应商表所有记录 -->

  <select id="queryAllProviders" resultType="entity.Provider">

    SELECT * FROM `smbms_provider`

  </select>

</mapper>

 

SQL映射文件常用元素介绍:

 

mapper:SQL映射文件的根节点,只有一个属性namespace

namespace:用于区分不同的mapper和关联Dao映射器接口

select:表示查询语句,常用属性:

  id:该命名空间下唯一标识符,一般与映射器接口中的方法同名

  resultType:SQL语句的返回值类型

 

(4).创建MyBatisUtil工具类,获取MyBatis核心API实例

private static SqlSessionFactory factory=null;

   

   //加载factory

   static

   {

   try

   {

   InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");

   factory=new SqlSessionFactoryBuilder().build(inputStream);

   }

   catch(Exception e)

   {

   e.printStackTrace();

   }

   }

   

   //获取SqlSession

   public static SqlSession getSqlSession()

   {

   //false手动提交事务

   return factory.openSession(false);

   }

   

   //关闭SqlSession释放资源

   public static void closeSqlSession(SqlSession sqlSession)

   {

   if(sqlSession!=null)

   {

   sqlSession.close();

   }

   }

 

(5) .创建测试类进行测试

 

 

4. MyBatis核心对象

SqlSessionFactoryBuilder

负责构建SqlSessionFactory对象,构建方式:

(1)获取MyBatis配置文件输入流对象

InputStream inputSteam=Resources.getResourceAsStream(“mybatis-config.xml”);

(2)build()方法返回SqlSessionFactory实例

SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);

 

拓展:build()方法常用的重载形式:

build(Reader reader)

Build(InputStream inputStream)

build(Configuration configuration)

 

生命周期:用过即丢,一旦创建了SqlSessionFactory对象后,这个SqlSessionFactoryBuilder类就不再需要存在了

最佳作用域:方法体,作为局部变量

SqlSessionFactory(MyBatis核心)

创建SqlSession实例的工厂。所有的MyBatis应用程序都是以SqlSessionFactory实例为核心。SqlSessionFactory实例可以通过SqlSessionFactoryBuilder对象来获得(详见上文),有了它之后,就可以通过调用他的openSession()方法获取SqlSession实例

 

注意:openSession()方法的参数为boolean值,SqlSessionFactory类提供了openSession()方法的重载形式。

True:自动提交事务(默认值)

False:手动提交事务

不带参数默认为true自动提交事务

一般建议手动提交事务,所以一般参数设置为false

 

SqlSessionFactory的生命周期和作用域:

生命周期:SqlSessionFactory实例一旦创建,就会在整个应用程序中始终存在,所有SqlSession共享一个SqlSessionFactory。没有理由销毁或者再次创建,这种存在于整个应用程序期间,并且同时只存在一个对象实例的模式就是单例模式(在应用运行期间有且仅有一个实例)

作用域:Application

 

SqlSession

SqlSession是用于执行持久化操作的对象,类似jdbc中的Connection,它提供了面向数据库执行SQL命令的所有方法,可以通过SqlSession实例直接执行已映射的SQL语句

 

SqlSession的生命周期和作用域:

生命周期:SqlSession对应着一次数据库会话,由于数据库回话不是永久的,因此SqlSession的生命周期也不应该是永久的。在每次访问数据库时都要重新创建(在一个SqlSession中可以执行多次SQL语句),但是如果关闭里SqlSession,那么就需要重新创建它。

注意:

(1)创建SqlSession对象的地方只有一个,即通过SqlSessionFactory对象的openSession()方法创建SqlSession对象。

(2)在多线程运行环境下,每个线程都有自己的SqlSession实例,SqlSession实例并不能被共享,也不是线程安全的。

作用域:Request或者方法体

(3) 使用完SqlSession后需要在finally块中关闭SqlSession对象,释放占用的内存资源。

(4) SqlSession的常用使用方式有两种:

※通过SqlSession实例直接运行已映射的SQL语句,例如:

sqlSession.selectList(“Mapper映射器包路径.方法名”);

※基于mapper接口方式操作数据

mapper接口的方法必须与SQL映射文件中SQL语句的id一一对应。

例如:

sqlSession.getMapper(UserMapper.class).findUserList();

 

 

5. MyBatis体系概述

MyBatis核心接口和类、MyBatis核心配置文件(mybatis-config.xml)、SQL映射文件(mapper.xml)

高级特性:支持动态SQL

 

 

6. SQL映射文件常用配置项

顶级配置项:

mapper 映射文件的根元素节点,只有一个属性namespace,其作用如下:

(1) .区分不同的mapper映射文件,保证namespace属性值全局唯一

(2) 绑定DAO接口(映射器接口),即面向接口编程。当namespace绑定某一接口之后,可以不用写该接口的实现类,MyBatis会通过接口的完整限定名查找到对应的Mapper配置来执行SQL语句。

注意:保证namespace的命名必须要跟接口同名

cache 配置给定命名空间的缓存

cache-ref 从其他命名空间引用缓存配置

resultMap 描述数据库结果集和对象的对应关系

sql可以重用的SQL语句块,也可以被其他语句引用。

Insert 映射插入语句

Update 映射修改语句

Delete 映射删除语句

Select 映射查询语句

属性:

id 命名空间下唯一的标识符,可以被用来引用这条语句,必须与该SQL映射文件绑定的映射器dao接口中的方法名一一对应

parameterType 表示查询语句传入参数的类型的完全限定名或别名,它支持基础数据类型和复杂数据类型。

常用类型别名:

别名          映射的类型

string         String

byte          Byte

long          Long

short          Short

int           Integer

integer       Integer

arraylist      ArrayList

double       Double

float        Float

boolean     Boolean

date        Date

map        Map

hashmap   HashMap

list        List

除了内建的类型别名之外,还可以在mybatis-config.xml核心配置文件中为自定义的JavaBean类指定别名(typeAliases元素),配置之后在SQL映射文件中可以直接使用别名,从而减少配置文件代码。

resultType 查询语句返回结果类型的完全限定名或别名,别名的使用方式与parameterType是一样的。

 

注意:

关于MyBatis的SQL映射文件中的mapper元素的namespace属性有如下要求:

(1) namespace命名必须要跟某个接口同名,同属于DAO层,代码结构上一般将该映射文件和DAO映射器接口放置在同一个package下,并且习惯上命名都是以Mapper结尾。

(2) 在不同的mapper映射文件中,子元素的id可以相同,MyBatis通过namespace和子元素的id联合进行区分。接口中的方法和SQL映射文件中SQL语句的id要一一对应。

 

 

7. SQL映射文件参数传递

(1) 基本数据类型作为参数

必须通过使用@Param注解实现

(2) 多条件查询处理方式:

*封装成JavaBean对象入参

#{对象的属性名}----------------->对象的属性值

*封装成map集合入参

#{map集合元素的key}------------>map结合元素的value

 

 

8. 使用resultMap映射查询结果集和实体类对象

注意:使用resultType属性进行自动映射时,要确保对象的属性名和查询结果集的字段名必须保持一致,如不一致,需要给查询结果集中的字段起别名,保证列名和属性一一对应

resultMap元素用来描述如何将查询结果集映射到Java对象,一般适用于两种情况:

(1) 查询结果集中的字段名和pojo属性名不一致,没有指定别名

(2) 多表连接查询

resultMap元素常用属性值和子节点:

id属性:唯一标示,此id对应select元素的resultMap属性

type属性:该resultMap的映射结果类型

result子节点:用于标识一些简单的属性,其中column属性表示从数据库中查询的字段名,property属性表示映射到pojo实体对象的哪个属性

 

注意:

对比select元素的resultType属性和resultMap属性

resultType直接表示返回结果类型,包括基础数据类型和复杂数据类型

resultMap则是对外部resultMap定义的引用,对应外部定义的resultMap的id,表示返回结果映射到哪一个resultMap上。它的应用场景一般是:数据库字段信息和对象属性不一致或者需要做复杂的联合查询,以便自由控制映射结果。

resultType和resultMap的关联:

在使用MyBatis框架进行查询映射的时候,其实查询出来的每个字段值都放在一个对应的Map里面,其中键是字段名,值是字段值,当select元素提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象的属性(即调用指定的对象属性的setter方法进行填充)。因为如此,在后台就可以直接取到其对应的对象的属性值。

其实MyBatis每个查询映射的返回类型都是resultMap,只是当我们提供的返回属性是resultType时,MyBatis会自动把对应的值赋给resultType所指定的对象的属性。但是当我们提供的返回类型是resultMap的时候,因为Map不能很好地表示领域模型,我们需要通过进一步的定义把他转化为对应的实体对象。

注意:在同一个select元素中,resultType和resultMap绝对不能同时存在,只能二者选用其中之一。

 

 

9. resultMap的自动映射级别

resultMap自动映射的三个匹配级别:

NONE:禁止自动匹配

PARTIAL(默认值):自动匹配所有,有内部嵌套(association/collection)除外

FULL:自动匹配所有

 

配置resultMap自动映射级别:

在mybatis-config.xml核心配置文件中配置:

<settings>

  <setting name=”autoMappingBehavior” value=”NONE | PARTIAL | FULL”>

</setting>

</settings>

 

 

10. MyBatis缓存

MyBatis提供了对一级缓存和二级缓存的支持

一级缓存:

一级缓存基于PerpetualCache(MyBatis自带)的HashMap本地缓存,作用范围是SqlSession域,当session被flush或者close后,该session中所有的cache缓存就会被清空

二级缓存:

二级缓存就是global caching,它超出session范围之外,可以被所有SqlSession共享,开启它仅需要在MyBatis核心配置文件mybatis-config.xml中配置即可,配置项如下:

<settings>

  <setting name=”cacheEnabled” value=”true”></setting>

</settings>

 

在mapper映射文件中设置缓存,默认情况下没有开启缓存。

注意:global cache的作用域是针对mapper的namespace属性而言的,即只有在此namespace内的查询才能共享这个cache

<mapper namespace=”dao.UserMapper”>

  <cache eviction=”FIFO”  flushInterval=”60000” size=”512” readOnly=”true”/>

</mapper>

 

在mapper文件中配置支持cache后,如果需要对个别查询进行调整,可以单独设置cache

<select id=”findUserInfo” parameterType=”entity.User” resultMap=”queryUser” useCache=”true”>

......

</select>

 

 

11. resultMap高级结果映射

(1) .POJO持久化类定义了一个POJO类型的属性

association元素:映射到JavaBean某个复杂类型的属性,如JavaBean类型的属性,即JavaBean内部嵌套了一个JavaBean属性。

属性:

property  映射数据库列的实体对象的属性名(JavaBean属性名)

javaType  JavaBean属性的类型,完整Java类名或别名

子元素:

Id

result

属性:

property 映射数据库列的实体对象的属性

column 数据库列名或别名

注意:association仅处理一对一关联关系

   <resultMap id="queryAssoBill" type="Bill">

     <result property="billCode" column="billCode"></result>

     <result property="productName" column="productName"></result>

     <result property="totalPrice" column="totalPrice"></result>

     <result property="isPayment" column="isPayment"></result>

     <association property="provider" javaType="Provider">

       <result property="proCode" column="proCode"></result>

       <result property="proName" column="proName"></result>

       <result property="proContact" column="proContact"></result>

       <result property="proPhone" column="proPhone"></result>

     </association>

   </resultMap>

(2) POJO持久化类定义了一个List集合类型的属性

collection元素:映射到JavaBean某个复杂类型的属性(集合列表List),

即在JavaBean内部嵌套了一个List集合类型的属性

属性:

property 映射数据库列的实体对象的属性(List集合属性名)

ofType  List集合属性类型的完整类名或别名

子元素:

Id

result

属性:

property 映射数据库列的实体对象的属性

column 数据库列名或别名

注意:collection适用于一对多关联映射

 

 

12. 动态SQL

动态SQL是MyBatis的一个强大特性,动态SQL基于OGNL表达式,可是我们方便地在SQL语句中实现某些逻辑,提高SQL映射文件中的SQL语句编写效率

(1) .动态SQL元素

①if 利用if实现简单的条件判断

属性:

test 条件表达式

 

②choose(when/otherwise) 相当于Java中的switch语句,通常与when和otherwise搭配使用

属性:

test 条件表达式

 

③where 简化SQL语句WHERE条件判断

自动剔除多余的AND前缀

④set 解决动态更新语句

自动剔除结尾多余的,逗号

⑤trim 可以灵活地添加或去除多余关键字

prefix 前缀

prefixOverrides 忽略前缀

suffix 后缀

suffixOverrides 忽略后缀

⑥foreach 迭代一个集合,通常用于IN()子查询条件

collection:

入参为数组=====>array

入参为List集合=====>list

入参为Map=====>Map元素的键

Item: 当前迭代项

Index:每次迭代到的位置

open该语句以什么开始

separator迭代项之间使用什么作为分隔符

close该语句以什么结束

 

例子:

①if多条件查询

  <!-- 使用if查询订单表信息 -->

  <select id="findBillInfoByIF" parameterType="Bill" resultMap="queryBill">

    SELECT b.*,p.`proName` FROM `smbms_bill` AS b,`smbms_provider` AS p

    WHERE b.`providerId`=p.`id`

    <if test="productName!=null and productName!=''">

      AND b.`productName` LIKE CONCAT('%',#{productName},'%')

    </if>

    <if test="providerId!=null and providerId!=0">

      AND b.`providerId`=#{providerId}

    </if>

    <if test="isPayment!=null and isPayment!=0">

      AND b.`isPayment`=#{isPayment}

    </if>

  </select>

②If+where实现多条件查询

  <!-- if+where查询供应商信息 -->

  <select id="findProviderInfoByIfAndWhere" resultMap="queryProvider">

    SELECT * FROM `smbms_provider`

    <where>

      <if test="proCode!=null and proCode!=''">

        AND `proCode` LIKE CONCAT('%',#{proCode},'%')

      </if>

      <if test="proName!=null and proName!=''">

        AND `proName` LIKE CONCAT('%',#{proName},'%')

      </if>

    </where>

  </select>

 

③if+trim多条件查询

<!-- if+trim分页查询角色信息 -->

  <select id="findRoleInfo" resultMap="queryRole">

    SELECT * FROM `smbms_role`

    <trim prefix="WHERE" prefixOverrides="and | or">

      <if test="roleName!=null and roleName!=''">

AND `roleName` LIKE CONCAT('%',#{roleName},'%')

</if>

    </trim>

    LIMIT #{curPageNo},#{pageSize}

  </select>

 

④if+set动态更新

<!-- if+set修改供应商表信息 -->

  <update id="updateProviderInfoByIfAndSet" parameterType="Provider">

    UPDATE `smbms_provider`

    <set>

      <if test="proCode!=null and proCode!=''">`proCode`=#{proCode},</if>

      <if test="proName!=null and proName!=''">`proName`=#{proName},</if>

      <if test="proDesc!=null and proDesc!=''">`proDesc`=#{proDesc},</if>

      <if test="proContact!=null and proContact!=''">`proContact`=#{proContact},</if>

      <if test="proPhone!=null and proPhone!=''">`proPhone`=#{proPhone},</if>

      <if test="proAddress!=null and proAddress!=''">`proAddress`=#{proAddress},</if>

      <if test="proFax!=null and proFax!=''">`proFax`=#{proFax},</if>

      <if test="modifyBy!=null and modifyBy!=0">`modifyBy`=#{modifyBy},</if>

      <if test="modifyDate!=null and modifyDate!=''">`modifyDate`=#{modifyDate},</if>

    </set>

    WHERE `id`=#{id}

  </update>

 

⑤if+trim动态更新

<!-- if+trim修改供应商表信息 -->

  <update id="updateProviderInfoByIfAndTrim" parameterType="Provider">

    UPDATE `smbms_provider`

    <trim prefix="SET" suffixOverrides="," suffix="WHERE `id`=#{id}">

      <if test="proCode!=null and proCode!=''">`proCode`=#{proCode},</if>

      <if test="proName!=null and proName!=''">`proName`=#{proName},</if>

      <if test="proDesc!=null and proDesc!=''">`proDesc`=#{proDesc},</if>

      <if test="proContact!=null and proContact!=''">`proContact`=#{proContact},</if>

      <if test="proPhone!=null and proPhone!=''">`proPhone`=#{proPhone},</if>

      <if test="proAddress!=null and proAddress!=''">`proAddress`=#{proAddress},</if>

      <if test="proFax!=null and proFax!=''">`proFax`=#{proFax},</if>

      <if test="modifyBy!=null and modifyBy!=0">`modifyBy`=#{modifyBy},</if>

      <if test="modifyDate!=null and modifyDate!=''">`modifyDate`=#{modifyDate},</if>

    </trim>

  </update>

 

⑥MyBatis入参为数组(Array)类型的foreach迭代

<!-- foreach入参数组类型,查询指定供应商下的订单信息 -->

  <select id="findBillInfoByArray" resultMap="queryBill">

    SELECT b.*,p.`proName` FROM `smbms_bill` AS b

    INNER JOIN `smbms_provider` AS p

    ON b.`providerId`=p.`id`

    WHERE b.`providerId` IN

    <foreach collection="array" item="providerId" open="(" separator="," close=")">

      #{providerId}

    </foreach>

  </select>

 

⑦MyBatis入参为List类型的foreach迭代

<!-- foreach入参list类型,查询指定供应商下的订单信息 -->

  <select id="findBillInfoByList" resultMap="queryBill">

    SELECT b.*,p.`proName` FROM `smbms_bill` AS b

    INNER JOIN `smbms_provider` AS p

    ON b.`providerId`=p.`id`

    WHERE b.`providerId` IN

    <foreach collection="list" item="providerId" open="(" separator="," close=")">

      #{providerId}

    </foreach>

  </select>

 

⑧MyBatis多参数入参,封装成Map类型的foreach迭代

<!-- foreach入参为map类型,查询指定订单编码和供应商id下的订单信息 -->

  <select id="findBillInfoByMap" resultMap="queryBill">

    SELECT b.*,p.`proName` FROM `smbms_bill` AS b

    INNER JOIN `smbms_provider` AS p

    ON b.`providerId`=p.`id`

    WHERE b.`billCode` LIKE CONCAT('%',#{billCode},'%')

    AND b.`providerId` IN

    <foreach collection="providerIds" item="providerId" open="(" separator="," close=")">

      #{providerId}

    </foreach>

  </select>

 

⑨choose(when/otherwise)动态查询

  <!-- choose(when/otherwise)查询供应商表信息 -->

  <select id="findProviderInfoByChoose" resultMap="queryProvider">

    SELECT * FROM `smbms_provider`

    WHERE 1=1

    <choose>

      <when test="proCode!=null and proCode!=''">AND `proCode` LIKE CONCAT('%',#{proCode},'%')</when>

      <when test="proName!=null and proName!=''">AND `proName` LIKE CONCAT('%',#{proName},'%')</when>

      <when test="proContact!=null and proContact!=''">AND `proContact` LIKE CONCAT('%',#{proContact},'%')</when>

      <otherwise>AND YEAR(`creationDate`)=#{creationDate}</otherwise>

    </choose>

  </select>

 

 

 

13. MyBatis实现分页

MySQL的分页是基于内存的分页,即查出来所有的记录,再按起始位置和页面容量取出结果集。

MyBatis实现分页步骤:

1. 使用聚合函数count()获得总记录数

2. 实现分页,通过LIMIT 起始位置,页面容量实现(起始位置从0开始)

例如:

<!-- if+trim分页查询角色信息 -->

  <select id="findRoleInfo" resultMap="queryRole">

    SELECT * FROM `smbms_role`

    <trim prefix="WHERE" prefixOverrides="and | or">

      <if test="roleName!=null and roleName!=''">AND `roleName` LIKE CONCAT('%',#{roleName},'%')</if>

    </trim>

    LIMIT #{curPageNo},#{pageSize}

  </select>

 

参数说明:

curPageNo,起始行索引,从0开始(不是页码):

起始行索引=(当前页码-1)*页面容量

pageSize页面容量

 

 

14. MyBatis参数入参补充说明

(1)MyBatis接受的参数类型:基本类型、对象、数组、List、Map

(2)无论MyBatis的入参是哪种类型,MyBatis都会将参数放在一个Map中。

(3)对于单参数入参的情况:

入参为基本类型===>变量名作为Key,变量值作为Value

入参为对象===>对象的属性名作为Key,对象的属性值作为Value

入参为数组===>array作为Key,该数组作为Value

入参为List集合===>list作为Key,该List集合作为Value

入参为Map===>键值不变

(4).对于多参数入参的情况:

入参均为基本数据类型,需要使用@Param注解

入参为复杂数据类型(如基本数据类型和复杂数据类型混合入参),需要将参数封装为一个Map,Map的key作为键,Map的value作为值。

(5) 关于#{参数名}和${参数名}的对比说明

#{参数名}

采用预编译的方式入参,作用类似于PreparedStatement

${参数名}

采用拼接字符串的方式入参,将${参数名}解析为一个变量,有SQL注入风险,使用较少,一般适用于自定义排序字段或排序方式。

例如:

<select id=”queryUsers” resultType=”entity.User”>

  SELECT * FROM `smbms_user`

  ORDER BY ${orderBy} ${orderWay}

</select>

 

模糊查询使用#{},配合MySQL的字符串拼接函数CONCAT()使用

 

15. MyBatis配置文件组成结构

mybatis-config.xml是MyBatis核心配置文件,MyBatis将在启动时加载该配置文件中的配置项,该配置文件用来定义通用的共享的MyBatis相关配置信息,这是使用传统xml配置的形式,该配置文件各配置元素是有顺序要求的,集成spring或springboot后可基于注解驱动配置则免于顺序要求,mybatis-config.xml常用配置项和顺序要求如下:

 

configuration 根节点,管理所有MyBatis配置项

   properties 可以引入在Java属性配置文件中配置的数据源文件(database.properties),也可以直接使用子元素property配置数据源

   settings 修改MyBatis运行时的行为方式

   typeAliases 为Java类型命名一个别名(简称)

   typeHandlers 类型处理器

   objectFactory 对象工厂

   plugins 插件

   environments 环境

       Environment 环境变量

         transactionManager 事务管理器

         dataSource 数据源

   mappers 映射器

 

配置项元素说明:

properties元素:描述外部化、可替代的属性。

(1)通过resource属性引入外部database.properties数据源配置文件

(2)通过定义子元素<property>直接配置数据源

 

settings元素:设置一些非常重要的设置选项,用于设置和改变MyBatis运行中的行为。常用配置项如下:

name属性       value属性     默认值

cacheEnabled:对在此配置文件下的所有cache进行全局性开关设置             true | false   true

lazyLoadingEnabled:全局性设置懒加载,如果设置为false,则所有相关联的都会被初始化加载,即立即加载模式  true | false   true

autoMappingBehavior:MyBatis对于resultMap的自动映射匹配级别  NONE | PARTIAL | FULL  PARTIAL

 

typeAliases元素:配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入多余的完整类名,简化操作。

子元素:typeAlias

属性:

alias 类型别名

type 完整类型限定名

子元素:package

属性:name 扫描制定包下的所有JavaBean并默认设置一个别名(默为类名)

 

environments元素:配置MyBatis多套运行环境,如开发环境、测试环境、生产环境等,可以灵活选择不同的配置,从而将SQL映射到不同的数据库环境。

注意:必须使用default属性指定默认运行环境。

子元素:

environment:MyBatis其中一套运行环境,需要指定id属性,并确保该id属性值全局唯一。

   子元素:

   transactionManager:事务管理器,设置其类型为JDBC,MyBatis有两种事务管理类型,JDBC和MANAGED.直接使用JDBC的提交和回滚功能,依赖于从数据源获得连接来管理事务的生命周期。

  dataSource:使用标准的JDBC数据源接口配置JDBC连接对象的资源。MyBatis提供了三种数据源类型(POOLED/UNPOOLED/JNDI),一般采用POOLED类型,表示使用数据库连接池的概念来管理数据库连接,有利于快速响应请求。

 

mappers:映射器,用来定义SQL映射语句,通过指定mapper子节点的resource属性引入SQL映射文件的类资源路径,如dao/UserMapper.xml

有两种方式引入SQL映射文件

(1) .类资源路径获取

<mappers>

  <mapper resource=”dao/UserMapper.xml”/>

</mappers>

(2) .使用URL获取资源

<mappers>

  <mapper =”file:///D:/dao/UserMapper.xml”/>

</mappers>

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值