第一章 MyBatis简介笔记

本文详细介绍了MyBatis ORM框架,包括MyBatis的概念、快速入门、配置方法,如environments、mapper配置、SQL映射及动态SQL,以及代码生成器MyBatis Generator的使用。还讨论了一级缓存和二级缓存的工作原理,强调了其在复杂查询和关联映射中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、MyBatis概念

1、为什么需要ORM框架?

传统的JDBC编程存在的弊端:

工作量大,操作数据库至少要5步;

业务代码和技术代码耦合;

连接资源手动关闭,带来了隐患

2、ORM是什么?

对象关系映射(ORM Obeject Relational Mapping),ORM模型就是数据库的表与简单Java对象(POJO)的映射模型,它主要解决数据库数据和POJO对象的相互映射;

ORM带来的好处:

更加贴合面向对象的编程语意,Java程序员喜欢的姿势;

技术和业务解耦,Java程序员无需对数据库相关的知识深入了解

妈妈再也不用担心我,不释放数据库连接资源了

3、ORM框架两大霸主

4Mybatis是什么?

Mybatis前身是iBatis,其源于“Internet”和“ibatis”的组合,本质是一种半自动的ORM框架,除了POJO 和映射关系之外,还需要编写SQL语句。Mybatis映射文件三要素:SQL、映射规则、POJO

二、Mybatis快速入门

1)加入mybatis的依赖

2)添加mybatis的配置文件

3)场景介绍

4)编写实体类、mapper接口以及mapper xml文件;

5)编写实例代码

SqlSessionFactoryBuilder:读取配置信息创建SqlSessionFactory,建造者模式,方法级别生命周期;SqlSessionFactory:创建Sqlsession,工厂单例模式,存在于程序的整个生命周期。

SqlSession:代表一次数据库连接,可以直接发送SQL执行,也可以通过调用Mapper访问数据库;线程不安全,要保证线程独享(方法级)。

SQL Mapper:由一个Java接口和XML文件组成,包含了要执行的SQL语句和结果集映射规则。方法级别生命周期。

1、Mybatis配置

第一种方式用的推荐使用,类文件和mapper文件可以不需要放在一个文件夹中,xml文件也不会和java文件混合在一起。

2、Mybatis配置 environments

Environment:元素是配置一个数据源的开始,属性id是它的唯一标识

transactionManager元素配置数据库事务,其中type属性有三种配置方式:

  • jdbc,采用jdbc的方式管理事务;
  • managed,采用容器的方式管理事务,在JNDI数据源中使用;
  • 自定义,自定义数据库事务管理办法;

dataSource元素配置数据源连接信息,type属性是连接数据库的方式配置,有四种配置方式:

  • UNPOOLED 非连接池方式连接
  • POOLED   使用连接池连接
  • JNDI  使用JNDI数据源
  • 自定义数据源

3、Mybatis配置 mapper

注意:第一种方式用的推荐使用,类文件和mapper文件可以不需要放在一个文件夹中,xml文件也不会和java文件混合在一起。

4、基于xml配置的映射器

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

cache-ref – 其他命名空间缓存配置的引用。

resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

sql – 可被其他语句引用的可重用语句块。

insert – 映射插入语句

update – 映射更新语句

delete – 映射删除语句

select – 映射查询语句

5、select元素

1)自动映射:

前提:SQL列名和JavaBean的属性是一致的;

自动映射等级autoMappingBehavior设置为PARTIAL,需要谨慎使用FULL;

使resultType;如果列名和JavaBean不一致,但列名符合单词下划线分割,Java是驼峰命名法,则mapUnderscoreToCamelCase可设置为true;

2)传递多个查询入参:

使用map传递参数;可读性差,导致可维护性和可扩展性差,杜绝使用;

使用注解传递参数;直观明了,当参数较少一般小于5个的时候,建议使用;

使用Java Bean的方式传递参数;当参数大于5个的时候,建议使用;

6、resultType还是resultMap

1)resultType元素

resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的

pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。

自动映射

·前提:SQL列名和JavaBean的属性是一致的;

·使用resultType,如用简写需要配置typeAliases (别名);

·如果列名和JavaBean不一致,但列名符合单词下划线分割,Java是驼峰命名法,则

mapUnderscoreToCamelCase可设置为true;

2resultMap元素 属性

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。

ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。

Id:当前命名空间中的一个唯一标识,用于标识一个result map.

Type:类的完全限定名, 或者一个类型别名 (内置的别名可以参考上面的表格).

autoMapping:如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属

性会覆盖全局的属性 autoMappingBehavior。默认值为:unset。

使用场景:

·字段有自定义的转化规则

·复杂的多表查询

3resultMap元素 子元素

Id一个 ID结果;标记出作为ID的结果可以帮助提高整体性能

Result注入到字段或JavaBean属性的普通结果

Association一个复杂类型的关联;许多结果将包装成这种类型

嵌套结果映射:关联可以指定为一个resultMap元素,或者引用一个

Collection一个复杂类型的集合

嵌套结果映射:集合可以指定为一个resultMap元素,或者引用一个

Discriminator使用结果值来决定使用哪个resultMap

·Case:基于某些值的结果映射

·嵌套结果映射:一个 case 也是一个映射它本身的结果,因此可以包含很多相 同的元素,或者它可以参照一个外部的 resultMap

7、id & result

id 和 result 都将一个列的值映射到一个简单数据类型(字符串,整型,双精度浮点数,日期等)的属性或字段,两者之间的唯一不同是, id 表示的结果将是对象的标识属性,这会在比较对象实例时用到。 这样可以提高整体的性能,尤其是缓存和嵌套结果映射(也就是联合映射)的时候。

Property:POJO中映射到列结果的字段或者属性。如果POJO的属性匹配的是存在的,和给定SQL列名(column元素)相同的,那么MyBatis就会自动映射;

Column:SQL中的列名,或者是列的别名。一般情况下,这和 传递给 resultSet.getString(columnName) 方法的参数一样。

javaType:配置的Java的类;

jdbcType:配置的数据库的类型;

typeHandler:类型处理器,使用这个属性,你可以覆盖默 认的类型处理器。这个属性值是一个类型处理 器实现类的完全限定名,或者是类型别名。

8、constructor构造方法配置

一个pojo不存在没有参数的构造方法,就需要使用constructor;

 为了通过名称来引用构造方法参数,你可以添加 @Param 注解,指定参数名称的前提下,以任意顺序编写 arg 元素

<constructor>

<idArg column="id" javaType="int" />

<arg column="user_name" javaType="String" />

</constructor>

9、insert, update 和 delete

Id命名空间中的唯一标识符,可被用来代表这条语句。

parameterType将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为MyBatis可以通过TypeHandler推断出具体传入语句的参数,默认值为unset。

flushCache将其设置为true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。

Timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为unset(依赖驱动)。

statementTypeSTATEMENT,PREPARED或CALLABLE的一个。这会让MyBatis分别使用Statement,PreparedStatement或CallableStatement,默认值:PREPARED。

useGeneratedKeys(仅对insert和update有用)这会令MyBatis使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键(比如:像MySQL和SQL Server这样的关系数据库管理系统的自动递增字段),默认值:false。

keyProperty(仅对insert和update有用)唯一标记一个属性,MyBatis会通过getGeneratedKeys的返回值或者通过insert语句的selectKey子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn(仅对insert和update有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

databaseId如果配置了databaseIdProvider,MyBatis会加载所有的不带databaseId或匹配当前 databaseId的语句;如果带或者不带的语句都有,则不带的会被忽略。

10、selectKey元素

keyPropertyselectKey语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

resultType结果的类型。MyBatis通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的Object或一个 Map。

Order这可以被设置为BEFORE或AFTER。如果设置为BEFORE,那么它会首先选择主键,设置keyProperty然后执行插入语句。如果设置为AFTER,那么先执行插入语句,然后是 selectKey元素-这和像Oracle的数据库相似,在插入语句内部可能有嵌入索引调用。

statementType与前面相同,MyBatis支持STATEMENT,PREPARED和CALLABLE语句的映射类型,分别代表PreparedStatement和CallableStatement类型。

<selectKey  keyProperty=“id” order= " Before" resultType="int">

select SEQ_ID.nextval from dual

</selectKey>

11、怎么传递多个参数?

使用map传递参数;可读性差,导致可维护性和可扩展性差,杜绝使用;

使用注解传递参数;直观明了,当参数较少一般小于5个的时候,建议使用;

使用Java Bean的方式传递参数;当参数大于5个的时候,建议使用;

12、怎么样获取主键?

insert标签相关属性

useGeneratedKeys(仅对insert和update有用)这会令MyBatis 使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。

keyProperty仅对insert和update有用)唯一标记一个属性,MyBatis会通过getGeneratedKeys 的返回值或者通过insert语句的selectKey子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

13、SQL的参数

sql元素:用来定义可重用的 SQL 代码段,可以包含在其他语句中;

参数:向sql语句中传递的可变参数

预编译 #{}:将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,能够很大程度防止sql注入;

传值 ${}:传入的数据直接显示生成在sql中,无法防止sql注入;

表名、选取的列是动态的,order by和in操作, 可以考虑使用$

注意:两者区别在于传入的参数 是否加了 ‘’引号,#是有占位符 ? 的 $是直接传入的参数

14、动态SQL

1)动态sql元素

If: 判断语句 单条件分支判断。

choose、when、otherwise:相当于java的case when 多条件分支判断。

Trim、where、set:辅助元素 用于处理sql拼装问题。

Foreach:循环语句 在in语句等列举条件常用,常用于实现批量操作。

2)批量操作

通过foreach动态拼装SQL语句

使用BATCH类型的excutor

15、注解方式配置

注解方式就是将SQL语句直接写在接口上,对于需求比较简单的系统,效率较高。缺点在于,每次修改sql语句都要编译代码,对于复杂的sql语句可编辑性和可读性都差,一般不建议使用这种配置方式;

@Select、@Results、@Insert、@Update、@Delete

 

三、代码生成器

1、Mybatis Generator (MBG)

MyBatis Generator:MyBatis 的开发团队提供了一个很强大的代码生成器,代码包含了数据库表对应的实体 类 、Mapper 接口类、 Mapper XML 文件和 Example 对象等,这些代码文件中几乎包含了全部的单表操作方法,使用 MBG 可以极大程度上方便我们使用 MyBatis,还可以减少很多重复操作。

generatorConfiguration – 根节点

properties – 用于指定一个需要在配置中解析使用的外部属性文件;

classPathEntry - 在MBG工作的时候,需要额外加载的依赖包;

context -用于指定生成一组对象的环境

• property (0 个或多个) - 设置一些固定属性

• plugin (0 个或多个)- 定义一个插件,用于扩展或修改通过 MBG 生成的代码

• commentGenerator (0 个或 1 个) - 该标签用来配置如何生成注释信息

• jdbcConnection ( 1 个)- 必须要有的,使用这个配置链接数据库

• javaTypeResolver ( 0 个或 1 个) - 指定 JDBC 类型和 Java 类型如何转换

• javaModelGenerator ( 1 个) - java模型创建器

• sqlMapGenerator (0 个或 1 个)- 生成SQL map的XML文件生成器

• javaClientGenerator (0 个或 1 个)- 生成Mapper接口

例如:generatorConfig.xml配置信息如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE generatorConfiguration PUBLIC   
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
 <!--
   1.从命令提示符 使用 XML 配置文件,使用场景:对逆向工程定制较少,项目工程结构比较复杂的情况
   java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml
   使用场景:对逆向工程定制较多,项目工程结构比较单一的情况:
   2. 作为 Maven Plugin 命令: mvn mybatis-generator:generate
   3. 从另一个 Java 程序 使用 XML 配置文件
  -->
<generatorConfiguration>
   <!-- 引入配置文件 -->
   <properties resource="db.properties" />
   <!-- 制定驱动的位置:D:/tools/mybatis-generator/mysql-connector-java-5.1.18.jar -->
   <classPathEntry location="${class_path}" />
   <!-- context:生成一组对象的环境
      id: 必选,上下文id,用于在生成错误时提示
      defaultModelType:指定生成对象的样式
         1,conditional:类似hierarchical;
         2,flat:所有内容(主键,blob)等全部生成在一个对象中,推荐使用;
         3,hierarchical:主键生成一个XXKey对象(key class),Blob等单独生成一个对象,其他简单属性在一个对象中(record class) targetRuntime:
         1,MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample
          2,MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample
     -->
   <context id="context1" targetRuntime="MyBatis3">
      <commentGenerator>
         <!-- 是否去除自动生成的注释 true:是 : false:否 -->
         <property name="suppressAllComments" value="true" />
      </commentGenerator>
         <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
      <jdbcConnection driverClass="${jdbc_driver}" connectionURL="${jdbc_url}" userId="${jdbc_username}" password="${jdbc_password}" />
 <!-- java模型创建器,是必须要的元素   负责:1,key类(见context的defaultModelType);2,java类;3,查询类
    targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
   targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
 -->
      <javaModelGenerator targetPackage="com.chj.mybatis.entity" targetProject="src/main/java" />
 <!-- 生成SQL map的XML文件生成器,
    targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
   targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
  -->
      <sqlMapGenerator targetPackage="." targetProject="src/main/resources/sqlmapper" />
       <!-- 对于mybatis来说,即生成Mapper接口,注意,如果没有配置该元素,那么默认不会生成Mapper接口
       type:选择怎么生成mapper接口(在MyBatis3/MyBatis3Simple下):
       1,ANNOTATEDMAPPER:会生成使用Mapper接口+Annotation的方式创建(SQL生成在annotation中),不会生成对应的XML;
     2,MIXEDMAPPER:使用混合配置,会生成Mapper接口,并适当添加合适的Annotation,但是XML会生成在XML中;
     3,XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
     注意,如果context是MyBatis3Simple:只支持ANNOTATEDMAPPER和XMLMAPPER
   -->    
      <javaClientGenerator targetPackage="com.chj.mybatis.mapper" targetProject="src/main/java" type="XMLMAPPER" />
      <!-- shema 数据库 tableName表名  tableName="%"表示生成所有表对应的映射关系-->
      <table schema="mybatis" tableName="%" enableCountByExample="false"
         enableUpdateByExample="false" enableDeleteByExample="false"
         enableSelectByExample="false" selectByExampleQueryId="false">
      </table>
   <!--   <table schema="${jdbc_username}" tableName="t_user"
          enableCountByExample="false"
         enableUpdateByExample="false" enableDeleteByExample="false"
         enableSelectByExample="false" selectByExampleQueryId="false">
      </table>
   </context>
</generatorConfiguration>

2、怎么运行MGB

1)从命令提示符 使用 XML 配置文件

java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml

2)使用场景:对逆向工程定制较少,项目工程结构比较复杂的情况作为:

Maven Plugin mvn mybatis-generator:generate

3)从另一个 Java 程序 使用 XML 配置文件使用场景:对逆向工程定制较多,项目工程结构比较单一的情况。

四、关联查询

在关系型数据库中,我们经常要处理一对一 、 一对多的关系 。 例如, 一辆汽车需要有一个引擎,这是一对一的 关系。 一辆汽车有 4 个或更多个轮子,这是一对多的关系 。关联元素就是专门用来处理关联关系的;

关联元素:

association 一对一关系

collection 一对多关系

discriminator 鉴别器映射

关联方式:

嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集

  1. 一对一 

1.1、一对一嵌套结果

association标签:嵌套结果方式 常用属性:

  • property:对应实体类中的属性名,必填项。
  • javaType:属性对应的 Java 类型 。
  • resultMap:可以直接使用现有的 resultMap ,而不需要在这里配置映射关系。
  • columnPrefix:查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀

Tips:

  • resultMap可以通过使用extends实现继承关系,简化很多配置工作量;
  • 关联的表查询的类添加前缀是编程的好习惯;
  • 通过添加完整的命名空间,可以引用其他xml文件的resultMap;

示例代码如下:

<select id="selectUserPosition1" resultMap="userAndPosition1">
   select user_name,real_name,sex,mobile,email,a.note,
      b.id  post_id,b.post_name,b.note post_note
   from t_user a,t_position b
   where a.position_id = b.id
</select>

1.2、一对一 嵌套查询

association标签:嵌套查询方式 常用属性:

  • select :另 一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果 。
  • column :列名(或别名),将主查询中列的结果作为嵌套查询的 参数。
  • fetchType :数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载 ,这个配置会覆盖全局的 lazyLoadingEnabled 配置;

Tips:“N+1 查询问题”:

概括地讲,N+1 查询问题可以是这样引起的:

·你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。

·对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

解决办法:使用“fetchType=lazy”并且全局setting进行改善:

<setting name="aggressiveLazyLoading" value="false"/>

示例代码:

<select id="selectUserPosition2" resultMap="userAndPosition2">
   select a.id, a.user_name,a.real_name, a.sex,a.mobile, a.position_id  from t_user a
</select>
<!-- 关联查询条件 -->
<resultMap id="userAndPosition2" extends="BaseResultMap" type="TUser">
   <association property="position"  column="position_id" select="com.chj.mybatis.mapper.TPositionMapper.selectByPrimaryKey" />
</resultMap>

2、一对多 

collection支持的属性以及属性的作用和association完全相同

mybatis会根据id标签,进行字段的合并,合理配置好ID标签可以提高处理的效率;

Tips:如果要配置一个相当复杂的映射,一定要从基础映射开始配置,每增加一些配置就进行对应的测试,在循序渐进的过程中更容易发现和解决问题。

示例代码如下:一对多 嵌套结果查询

<!--   一对多关系  嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型  -->
<resultMap id="userAndJobs1" extends="BaseResultMap" type="TUser">
   <collection property="jobs" ofType="com.chj.mybatis.entity.TJobHistory">
      <result column="comp_name" property="compName" jdbcType="VARCHAR" />
      <result column="years" property="years" jdbcType="INTEGER" />
      <result column="title" property="title" jdbcType="VARCHAR" />
   </collection>
</resultMap>
<!-- 一对多 嵌套结果查询 -->
<select id="selectUserJobs1" resultMap="userAndJobs1">
   select a.id,a.user_name,a.real_name,a.sex,a.mobile,b.comp_name,b.years,b.title
   from t_user a, t_job_history b
   where a.id = b.user_id
</select>

一对多 嵌套查询:

<!-- 一对多 嵌套查询 -->
<resultMap id="userAndJobs2" extends="BaseResultMap" type="TUser">
   <collection property="jobs" fetchType="lazy" column="id" select="com.chj.mybatis.mapper.TJobHistoryMapper.selectByUserId" />
</resultMap>
<select id="selectUserJobs2" resultMap="userAndJobs2">
   select a.id,a.user_name,a.real_name,a.sex,a.mobile from t_user a
</select>

3、多对多

先决条件一:多对多需要一种中间表建立连接关系;

先决条件二:多对多关系是由两个一对多关系组成的,一对多可以也可以用两种方式实现;

@Test
public void testManyToMany() {
   // 2.获取sqlSession
   SqlSession sqlSession = sqlSessionFactory.openSession();
   // 3.获取对应mapper
   TUserMapperExt mapper = sqlSession.getMapper(TUserMapperExt.class);
   // 4.执行查询语句并返回结果
   //嵌套结果
   List<TUser> list = mapper.selectUserRole();
   for (TUser tUser : list) {
      System.out.println("tUser.getRoles().size=="+tUser.getRoles().size());
   }
   // 嵌套查询
   TRoleMapper roleMapper = sqlSession.getMapper(TRoleMapper.class);
   List<TRole> roles = roleMapper.selectRoleandUsers();
   System.out.println("================主表查询结束=====================");
   for (TRole tRole : roles) {
      System.out.println("tRole.getUsers()=="+tRole.getUsers());
   }
}

Sql语句:

<!-- 多对多查询 嵌套结果-->
<resultMap id="userRoleInfo" type="TUser" extends="BaseResultMap">
   <collection property="roles" ofType="TRole" columnPrefix="role_">
      <result column="id" property="id" />
      <result column="Name" property="roleName" />
      <result column="note" property="note" />
   </collection>
</resultMap>
<select id="selectUserRole" resultMap="userRoleInfo">
   select a.id,
      a.user_name,
      a.real_name,
      a.sex,
      a.mobile,
      a.position_id,
       b.role_id,
       c.role_name,
       c.note role_note
   from t_user a,
        t_user_role b,
        t_role c
   where a.id = b.user_id AND
         b.role_id = c.id
</select>

 

<!-- 多对多查询 嵌套查询-->
<resultMap id="RoleandUsers" type="TRole" extends="BaseResultMap">
  <collection property="users" fetchType="lazy"  column="id" select="com.chj.mybatis.mapper.TUserMapperExt.selectUserByRoleId"></collection>
</resultMap>

<select id="selectRoleandUsers" resultMap="RoleandUsers">
  select
  <include refid="Base_Column_List" />
  from t_role
</select>

<!-- 多对多 嵌套查询 -->
<select id="selectUserByRoleId" resultMap="userRoleInfo">
   select 

<include refid="Base_Column_List" />
   from t_user a,
   t_user_role b
   where a.id = b.user_id and
   b.role_id = #{id}
</select>

运行结果:

4、discriminator鉴别器映射

在特定的情况下使用不同的pojo进行关联,鉴别器元素就是被设计来处理这个情况的。鉴别器非常容易理解,因为它的表现很像 Java 语言中的 switch 语句;

discriminator标签常用的两个属性如下:

column:该属性用于设置要进行鉴别比较值的列 。

javaType:该属性用于指定列的类型,保证使用相同的Java类型来比较值。

discriminator标签可以有1个或多个case 标签,case标签包含以下三个属性:

value:该值为discriminator指定column用来匹配的值 。

resultMap:当column的值和value的值匹配时,可以配置使用resultMap指定的映射,resultMap优先级高于resultType。

resultType:当column的值和value的值匹配时,用于配置使用resultType指定的映射。

鉴别器查询代码示例:

<!--   鉴别器映射 鉴别器非常容易理解,因为它的表现很像 Java 语言中的 switch 语句 -->
<resultMap id="userAndHealthReportMale" extends="userAndHealthReport" type="TUser">
   <!-- 一对多 property="healthReports"(List<HealthReport> healthReports) 对应实体类中的属性名,必填项。-->
   <collection property="healthReports" column="id"
      select= "com.chj.mybatis.mapper.THealthReportMaleMapperExt.selectByUserId"></collection>
</resultMap>
<resultMap id="userAndHealthReportFemale" extends="userAndHealthReport" type="TUser">
   <!-- 一对多  property="healthReports"(List<HealthReport> healthReports) 对应实体类中的属性名,必填项。-->
   <collection property="healthReports" column="id"
      select= "com.chj.mybatis.mapper.THealthReportFemaleMapperExt.selectByUserId"></collection>
</resultMap>
<!--  根据<case value="1" 来选择需要查询的 resultMap -->
<resultMap id="userAndHealthReport" extends="BaseResultMap" type="TUser">
   <discriminator column="sex"  javaType="int">
      <case value="1" resultMap="userAndHealthReportMale"/>
      <case value="2" resultMap="userAndHealthReportFemale"/>
   </discriminator>
</resultMap>
<select id="selectUserHealthReport" resultMap="userAndHealthReport">
   select <include refid="Base_Column_List" />
   from t_user a
</select>

 

五、Mybatis缓存

1、一级缓存

一级缓存 (也叫应用缓存):MyBatis 包含一个非常强大的查询缓存特性,使用缓存可以使应用更快地获取数据,避免频繁的数据库交互。

1)一级缓存默认会启用,想要关闭一级缓存可以在select标签上配置flushCache=“true”;

2)一级缓存存在于 SqlSession 的生命周期中,在同一个 SqlSession 中查询时, MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象;

3)任何的 INSERT 、UPDATE 、 DELETE 操作都会清空一级缓存;

2、二级缓存

二级缓存 (也叫应用缓存): 

二级缓存存在于SqlSessionFactory的生命周期中,可以理解为跨sqlSession;缓存是以namespace为单位的,不同namespace下的操作互不影响。

setting参数cacheEnabled,这个参数是二级缓存的全局开关,默认值是true,如果把这个参数设置为false,即使有后面的二级缓存配置,也不会生效;

要开启二级缓存,你需要在你的 SQL 映射文件中添加配置:

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

字面上看就是这样,这个简单语句的效果如下: 

• 映射语句文件中的所有 select 语句将会被缓存。

• 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

• 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

• 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

• 缓存会存储列表集合或对象(无论查询方法返回什么)的 512个引用。

• 缓存会被视为是 read/write(可读/可写)的缓存;

注意:

使用二级缓存容易出现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值