文章目录

  • 1、参数
  • 2、结果映射
  • 2.1、resultMap 元素的属性
  • 2.2、id 和 result 元素
  • 2.3、constructor 元素
  • 2.4、association 元素
  • 2.5、collection 元素
  • 2.5、discriminator 元素
  • 3、缓存
  • 3.1、一级缓存
  • 3.2、二级缓存
  • 3.3、共享相同的缓存配置


1、参数

在映射文件中的select、insert、update、delete元素中都有parameterType属性,这个属性就是用于确定参数的类型,可以是原始类型、简单数据类型或对象,它的值可以是别名也可以是全限定名。

<select id="selectUsers" parameterType="int" resultType="User">
  select *
  from users
  where id = #{id}
</select>

当传入单个参数时,parameterType可以省略,MyBatis 会自动设置。且#{id}中的id可以随意命名,当然最好还是按规范命名,在之后进行整合时更加方便。

<select id="selectUser" resultType="com.***.User" parameterType="com.***.User">
  select *
  from users
  where id = #{id}
</select>

当传入 java 对象类型的参数时,会根据#{参数名称}中的名称查找对象中的字段,然后将它们的值传入预处理语句的参数中。在使用#{id}完成预处理语句的设置时,还可以设置参数:

<select id="selectUser" resultType="com.***.User" parameterType="com.***.User">
  select *
  from users
  where id = #{id,javaType=double,jdbcType=NUMERIC,typeHandler=MyTypeHandler,numericScale=2}
</select>

{id,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler,numericScale=2}使用的一些属性 :

  • id:表示具体的属性值
  • javaType :表示参数在 java 中的数据类型
  • jdbcType:表示参数在数据库中的数据类型
  • typeHandler:表示使用规定的类型处理器,一般可以省略,除非该属性需要使用自定义类型处理器
  • numericScale:数值类型,用于指定小数点后保留的位数。

2、结果映射

resultMap 元素是 MyBatis 中用于返回结果的元素,之前你已经见过简单映射语句的示例,我们并没有显示的配置resultMap元素。

<select id="selectUsers" resultType="User">
  select *
  from users
  where id = #{id}
</select>

在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap元素,再根据属性名来映射列到 JavaBean 的属性上。在一般情况下,这种方式就已经猪足够使用了,但是在遇到多表查询等情况时,我们就需要显示的创建resultMap元素。在使用了resultMap元素之后:

<resultMap id="userResultMap" type="com.***.User">
  <id property="user_id" column="id" />
  <result property="user_name" column="name"/>
  <result property="user_age" column="age"/>
</resultMap>
<select id="selectUsers" resultType="userResultMap">
  select *
  from users
  where id = #{id}
</select>

那么我们具体来了解一下resultMap元素,它子元素比较多,讨论起来比较宽泛:

  • constructor:实例化的时,通过构造器将结果集注入到类中
  • idArg-ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
  • arg - 注入构造器的结果集
  • id :结果集ID,将结果集标记为ID,以方便全局调用
  • result:注入一个字段或者javabean属性的结果
  • association: 复杂类型联合;许多查询结果合成这个类型
  • collection:复杂类型集合
  • discriminator:使用一个结果值以决定使用哪个resultMap
  • case:基于不同值的结果映射

2.1、resultMap 元素的属性

resultMap 元素本身有三个属性:

  • id:结果集的唯一标识,用于标识一个结果映射。
  • type:类的完全限定名, 或者一个类型别名
  • autoMapping :是否开启自动映射

2.2、id 和 result 元素

idresult 元素是最基本的结果集映射,它们将列映射到属性或简单的数据类型字段(String, int, double, Date等)。id元素用于为主键映射;result元素用于其他基本数据库表字段到实体类属性的映射。

属性

Value

property

需要映射到 JavaBean 的属性名称。

column

数据表的列名或者标签别名。

javaType

一个完整的类名,或者是一个类型别名。如果你匹配的是一个JavaBean,那MyBatis 通常会自行检测到。

jdbcType

数据表支持的类型列表。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果你是直接针对JDBC 编码,且有允许空的列,而你要指定这项。

typeHandler

使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。

最主要的还是property column两个属性。

2.3、constructor 元素

constructor 元素和idresult元素作用差不多。idresult是通过 set 方法来赋值。而在某些特定情况下,不能使用 set 方法时,那么我们可以使用该constructor 元素。它的作用是:构造方法来实现值的映射,当然必须提供一个有参构造函数。在这个元素中,有两个子元素idArgage,它们具体的作用和idresult相同。这两个元素的具体属性:

属性

Value

column

数据库中的列名,或者是列的别名。

name

构造方法形参的名字。

select

用于加载复杂类型属性的映射语句的 ID,它会从 column 属性中指定的列检索数据,作为参数传递给此 select 语句。具体请参考关联元素。

resultMap

结果映射的 ID,可以将嵌套的结果集映射到一个合适的对象树中。

javaType

同上

jdbcType

同上

typeHandler

同上

最主要的还是javaTypename column三个属性。

2.4、association 元素

用于数据库一对一关系。 例如,有一个登录表和用户表,在用户登录成功之后,我们需要获取到用户表的信息。

<!-- 查询用户表 -->
<select id="selectUser" resultMap="userResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>
<!-- 查询登录表 -->
<select id="selectCard" resultType="com.***.Card">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
<!--定义 selectUser 表的结果集 -->
<resultMap id="userResult" type="com.***.User">
  <id column="id" property="id"></id>
  <result column="name" property="name"></result>
  <result column="age" property="age"></result>
  <association property="card" column="id" javaType="com.***.Card" select="selectCard">
</resultMap>

上述代码的执行流程:

  1. 调用selectUser语句,会根据传入的参数进行查询,然后查询结果进入userResult结果集进行处理
  2. 在结果集出来过程中,结果集会去执行associationselect属性所指的selectCard 语句,并且再执行过程中将column属性对应的值传过去。
  3. selectCard 语句查询到的结果隐式的使用resultMap元素将查询注入到 Card 对象中,然后将其的数据返回给userResult结果集,然后注入给 User 对象的 card 属性。

其实我们在中间省略了一步创建selectCard语句结果集的代码,我们也可以添加上去:

<!-- 查询用户表 -->
<select id="selectUser" resultMap="userResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>
<!-- 查询登录表 -->
<select id="selectCard" resultMap="cardResult">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>

<!--定义 selectCard 的结果集 -->
<resultMap id="cardResult" type="com.itlong.domain.Card">
  <id column="id" property="id"></id>
  <result column="name" property="name"></result>
  <result column="pass" property="pass"></result>
</resultMap>

<!--定义 selectUser 的结果集 -->
<resultMap id="userResult" type="com.***.User">
  <id column="id" property="id"></id>
  <result column="name" property="name"></result>
  <result column="age" property="age"></result>
  <association property="card" column="id" javaType="com.***.Card" select="selectCard">
</resultMap>

这种方式是通过两条 SQL 语句分别执行,还有另外一种方法如下:

<select id="findByUserId_2" resultMap="userResult_2">
   select *,u.id as id,u.name as user_name,c.name as card_name
   from user u,card c where u.id = c.id and u.id =#{id}
</select>

<resultMap id="userResult_2" type="com.itlong.domain.User">
   <id column="id" property="id"></id>
   <result property="name" column="user_name"></result>
   <result property="age" column="age" ></result>
   <association property="card" javaType="com.itlong.domain.Card">
       <id column="id" property="id"></id>
       <result property="name" column="card_name" ></result>
       <result column="pass" property="pass"></result>
   </association>
</resultMap>

这种方式还有可以将 association 元素的结果映射提取出来:

<!-- sql 语句映射不变,只改变结果集 -->
<resultMap id="userResult_2" type="com.itlong.domain.User">
   <id column="id" property="id"></id>
   <result property="name" column="user_name"></result>
   <result property="age" column="age" ></result>
   <association property="card" javaType="com.itlong.domain.Card" resultMap="cardResult_2">
   </association>
</resultMap>
<resultMap id="cardResult_2"  type="com.itlong.domain.Card">
   <id column="id" property="id"></id>
   <result property="name" column="card_name" ></result>
   <result column="pass" property="pass"></result>
</resultMap>

association 元素的一些常用属性:

属性

Value

property

映射到对象的字段或属性。

column

数据库中的列名,或者是列的别名。

javaType

一个 Java 类的完全限定名,或一个类型别名

select

用于调用其他映射语句的 ID

resultMap

结果映射的 ID

2.5、collection 元素

用于数据库一对多和多对多关系。 collection 元素和association元素几乎是一样的,它们的相似度很高。我们还是拿登录表和用户表来解析:

//讲解 association 元素时定义的 两个数据模型
public class User {
    private int id;
    private String name;
    private int age;
    private Card card;
    //省略 get/set 方法
}
public class Card {
    private int id;
    private String name;
    private int pass;
    //省略 get/set 方法
}

在讲解 association 元素时定义的两个数据模型,我们可以看出 User 表中的 card 属性就是用于映射 Card 表的。如果现在用户表对应多个登录。那么我们修改 User 表数据了:

public class User {
    private int id;
    private String name;
    private int age;
    private list<Card> card;
    //省略 get/set 方法
}

那在这种情况下,我们就需要使用collection元素了,且只能使用collection元素,其具体的使用规则和association一样这里不做重复叙述了。唯一多的一个比较重要的属性是ofType属性,用于指定 List 的泛型的类型

2.5、discriminator 元素

discriminator元素是表示在不不同情况下使用不同的 POJO。例如,某人家里有好小轿车,但是小轿车的种类却不同,比如有 电动汽车 和 传统汽车,我们需要按需来创建不同的 POJO。这时我们就需要在汽车类中添加types属性进行判断,同时还要创建两个类继承汽车类。

<select id="findBankCarId" parameterType="long" resultMap="carResult">
    SELECT id, car_name, car_price, types FROM car WHERE id = #{id}
</select>
<resultMap id="carResult"  type="com.itlong.domain.Car">
   <id column="id" property="id"></id>
   <result property="name" column="car_name" ></result>
   <result property="price" column="car_price" ></result>
   <!-- 将查询结果中 列名为 types 的进行处理 -->
   <discriminator javaType="int" column="types">
        <!-- types 为 1时寻找 结果集 elecars -->
        <case value="1" resultMap="elecars"></case>
        <!-- types 为 2时寻找 结果集 tradcars -->
        <case value="2" resultMap="tradcars"></case>
    </discriminator>
</resultMap>

<!-- types 为 1时使用,通过 Elecars 类实例化 父类 Car -->
<resultMap id="elecars" type="com.***.Elecars" extends="carResult"/>
<!-- types 为 1时使用,通过 Tradcars 类实例化 父类 Car -->
<resultMap id="tradcars" type="com.***.Tradcars" extends="carResult"/>

3、缓存

MyBatis 内置了一个强大的事务性查询缓存机制,分为一级缓存和二级缓存, 默认的情况下, 只开启一级缓存。

3.1、一级缓存

当使用同一个 SqlSession 对象执行同一个 SQL 语句两次时,其实只有第一次查询发送了 SQL 语句,第二次查询根本没有发送 SQL 语句, 直接从内存中获取了结果,获取到对象是相同的。

mysql映射boolean mybatis映射number类型_mybatis


如果使用不同的 SqlSession 对象执行同一个 SQL 语句两次时,两次查询都分别从数据库中取出了数据。 虽然结果相同, 但两个是不同的对象。

在使用一级缓存时:

  • 在同一个 SqlSession 对象中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;
  • 不同的 SqlSession 对象之间的缓存是相互隔离的;
  • 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。

3.2、二级缓存

要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:<cache/>。当然它有几个属性:

  • flushInterval:刷新间隔,单位毫秒。默认值不设置, 即没有刷新间隔,缓存仅仅在刷新语句时刷新。如果设定了之后, 到了对应时间会过期, 再次查询需要从数据库中取数据。
  • size:对应为引用的数量,即最多的缓存对象数据, 默认为 1024。
  • readOnly:表示是否只读。可读写(默认为 false)的缓存会(通过序列化)返回缓存对象的拷贝,速度上会慢一些,但是更安全。
  • eviction:表示缓存的回收策略, 默认为 LRU
  • LRU:最近最少使用, 移除最长时间不被使用的对象。
  • FIFO::FIFO: 先进先出, 按对象进入缓存的顺序来移除对象。
  • SOFT: 软引用, 移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK :弱引用, 移除基于垃圾回收器状态和弱引用规则的对象。

3.3、共享相同的缓存配置

在多个映射文件中,我们可以需要配置相同的缓存配置,如果都配置就会造成配置代码重复的弊病。所以我们可以定义一次,然后再其他映射文件引用缓存。引用代码:<cache-ref namespace="com.***.XXXMapper"/>,其中namespace属性就是表示需要引用缓存配置的映射文件