文档章节

MyBatis入门(三) -- 映射文件

兴趣使然的程序员
 兴趣使然的程序员
发布于 2017/08/20 14:39
字数 3215
阅读 9
收藏 0
点赞 0
评论 0

映射文件是所有 SQL 语句放置的地方,写好 SQL 语句映射文件后,需要在配置文件的 mappers 标签中引用。映射文件和与它具有相同功能的 JDBC 代码相比省掉了大部分的代码,而且对 SQL 的构建比普通方法还要好,这就是 MyBatis 的强大之处。

映射文件包含的顶级元素:

  • cache:给定命名空间的缓存配置。
  • cache-ref:其他命名空间缓存配置的引用。
  • resultMap:描述如何从数据库结果集中来加载对象。
  • sql:可被其他语句引用的可重用语句块。
  • insert:映射插入语句
  • update:映射更新语句
  • delete:映射删除语句
  • select:映射查询语句

1、resultMap

通常在<select>标签中,我们需要使用resultType定义返回值的类型,比如:

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

在这种情况下,我们的 resultType 为 User ,MyBatis 会在幕后自动创建一个 resultMap基于属性名来映射列到 JavaBean 的属性上

注意,使用默认的resultType要求列名和属性名完全匹配。如果列名和属性名不匹配,不会报异常,但是会使查出来的不匹配的列的值为Null

这时候我们就需要使用resultMap,比如:

<resultMap id="userMap" type="User">
      <!--属性名和列名并不完全匹配-->
      <id property="id" column="user_id" />
      <result property="username" column="user_name"/>
      <result property="password" column="user_password"/>
      <result property="sex" column="user_sex"/>
    <result property="address" column="user_sex"/>
</resultMap>


<select id="selectUsers" resultMap="userMap">
  select user_id, user_name, user_password, user_sex, user_sex
  from user
  where id = #{id}
</select>

resultMap 的子元素包括:

  • constructor:用来将结果注入到一个实例化好的类的构造方法中
    • idArg: ID 参数,标记结果作为 ID
    • arg:注入到构造方法的一个普通结果
  • id: 一个 ID 结果,标记结果作为 ID
  • result:注入到字段或 JavaBean 属性的普通结果
  • association:复杂的类型关联,多个结果合成的类型
    • 嵌入结果映射:结果映射自身的关联,也可以引用一个外部结果映射
  • collection:复杂类型的集 也可以引用一个外部结果映射
  • discriminator:使用结果值来决定使用哪个结果集
    • case:基本一些值的结果映射
      • 也可以引用一个外部结果映射

resultMap 的属性包括:

  • id :当前命名空间中的一个唯一标识,用于标识一个 resultMap
  • type:类的全限定名, 或者一个类型别名
  • autoMapping:为这个ResultMap开启或者关闭自动映射,该属性会覆盖全局的属性 autoMappingBehavior。默认值为:unset

1.1、resultMap的属性

1.1.1、id和result

id 和 result 都是映射一个单独列的值到简单数据类型(数值型、字符串和日期等)的单独属性或字段 。唯一不同的是 id 为主键映射,而 result 为其他数据库表字段到 JavaBean 属性的映射

属性 描述
property 映射到 JavaBean 的属性
column 数据库的列名或列名的重命名标签
javaType 一个 Java 类的完全限定名,或一个类型别名 。如果你映射到一个 JavaBean , MyBatis 通常可以断定类型。如果你映射到的是 HashMap,应该明确地指定 javaType 来保证所需的行为
jdbcType 所支持的 JDBC 类型,其仅作用在对插入,更新和删除操作允许为空的列。这是 JDBC 的需要,而 MyBatis 不需要。如果直接使用 JDBC 编程,需要指定这个类型且有允许为空的列,一般来说不需要指定。

1.1.2、discriminator

有时一个单独的数据库查询也许返回很多不同 (但是希望有些关联) 数据类型的结果集。 鉴别器元素就是被设计来处理这个情况的, 还有包括类的继承层次结构,它很像 Java 语言中的 switch 语句

下面的例子,当 sex 为 male ,才映射 sex 的属性

<resultMap id="userMap" type="User">
    <id property="id" column="id" javaType="int"/>
    <result property="username" column="username" javaType="String"/>
    <result property="password" column="password" javaType="String"/>
    <discriminator javaType="String" column="sex">
        <case value="male" resultType="sexResult">
            <result property="sex" column="sex" javaType="String"/>
        </case>
     </discriminator> 
    <result property="address" column="address" javaType="String"/>
</resultMap>

1.2、resultMap的属性

resultMap 的属性包括:

  • id :当前命名空间中的一个唯一标识,用于标识一个 resultMap
  • type:类的全限定名, 或者一个类型别名
  • autoMapping:为这个ResultMap开启或者关闭自动映射,该属性会覆盖全局的属性 autoMappingBehavior。默认值为:unset。一般不需要指定

2、select

在 MyBatis 中,对于每个 insert 、update 或 delete 操作通常对应多个 select 操作。

例如一个简单的查询:

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

这个语句被叫做 selectUserById ,有一个 int(即 Integer) 型参数,返回一个 User 类型的对象。

注意参数符号:#{id}

上述语句对于的 JDBC 语句如下:

String selectUserById = "select * from user where id=?";
PreparedStatement ps = conn.prepareStatement(selectUserById);
ps.setInt(1,id);

select 的属性:

属性 描述
id 命名空间中唯一的标识符,可被其他语句引用
parameterType 传入该语句的参数的完全限定名或别名
resultType 该语句返回类型的完全限定名或别名,注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身
resultMap 外部 resultMap 的命名引用
flushCache 任何语句的调用都会导致本地缓存和二级缓存被清空,默认为 false
useCache 导致本条语句的结果被二级缓存,默认为 true
timeout 设置驱动器在抛出异常前数据库返回请求结果的秒数,默认为 unset(依赖驱动)
fetchSize 尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认为 unset(依赖驱动)
statementType 让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认为 PREPARED
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认为 unset(依赖驱动)
databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略
resultOrdered 仅针对嵌套结果 select 语句适用,如果为 true,就是假设包含了嵌套结果集或是分组了,默认为 false
resultSets 仅对多结果集适用,它将列出返回的结果集并为每个结果集给一个名称,名称用逗号分隔

注:返回时可以使用 resultType 或 resultMap,但不能同时使用。

3、insert、update 和 delete 

3.1、insert

例如一个插入操作:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into user (username,password,sex,address) values (#{username},#{password},#{sex},#{address})
</insert>

这里使用了 useGeneratedKeys 来实现自动生成主键策略,然后把 keyProperty 设成对应的属性,在插入成功时,就返回这个自动生成的主键。

3.2、update

例如一个更新操作:

<update id="updateUser"  parameterType="User">
    update user set
    address=#{address} 
    where id=#{id}
</update>

3.3、delete

例如一个删除操作:

<delete id="deleteUser" parameterType="int">
    delete from user where id=#{id}
</delete>

insert 、update 和 delete 的属性:

属性 描述
id 命名空间中唯一的标识符,可被其他语句引用
parameterType 传入该语句的参数的完全限定名或别名
flushCache 任何语句的调用都会导致本地缓存和二级缓存被清空,默认为 false
timeout 设置驱动器在抛出异常前数据库返回请求结果的秒数,默认为 unset(依赖驱动)
statementType 让 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 的语句;如果带或者不带的语句都有,则不带的会被忽略

注:useGeneratedKeyskeyProperty 和 keyColumn 仅对 insert 和 update有用。同时只有数据库支持自增长主键字段(比如 MySQL、SQL Server)才可以设置 useGeneratedKeys="true",像 Oracle 则不支持自增长 id,如果设置 useGeneratedKeys="true" 就会报错。

3.4、selectKey

对于不支持自增长 id 的 JDBC 驱动来说, MyBatis 采用 selectKey 来生成主键

举个例子:

<insert id="insertUser">
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
         select seq_users.nextval from dual
      </selectKey>
    insert into user (username,password,sex,address) values (#{username},#{password},#{sex},#{address})
</insert>

上述代码使用语句 select seq_users.nextval from dual 生成一个 key 。

selectKey 的属性:

属性 描述
keyProperty selectKey 语句结果应该被设置的目标属性
keyColumn 匹配属性的返回结果集中的列名称
resultType 结果的类型, MyBatis 允许任何简单类型(包括字符串)作为主键的类型
order 可设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行 insert 语句。如果设置为 AFTER,那么先执行 insert 语句,然后是 selectKey ,这和像 Oracle 的数据库相似,在 insert 语句内部可能有嵌入索引调用
statementType 让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认为 PREPARED

3.5、parameterType

在 SQL 映射语句中使用了参数 parameterType , MyBatis 可以使用基本数据类型Java 复杂数据类型

(1)基本数据类型参数

根据 id 查询用户信息

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

(2)Java 实体类型参数

插入一条用户信息

<select id="insertOneUser" parameterType="User" >
    insert into user (id,username,password,sex,address) values
    (#{id},#{username},#{password},#{sex},#{address})
</select>

(3)Map 参数

根据 username 和 sex 查询用户信息

<select id="selectUserByNameAndSex" parameterType="map" resultType="User">
    select * from user where name=#{name} and sex=#{sex}
</select>

(4)字符串替换

默认情况下,使用 #{} 格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(比如?),这样做更安全,更迅速。如果想直接在 SQL 语句中插入一个不改变的字符串。比如,像 ORDER BY,可以使用: ORDER BY ${columnName},这里 MyBatis 不会修改或转义该字符串。

注: 以上述方法接受用户的输入数据是不安全的,容易造成 SQL 注入攻击。因此,要么不允许用户输入,要么自行转义并检验。

4、sql

sql 元素可以定义可复用的 SQL 代码段,供其他语句调用。如:

<sql id="selectAllUser">  
    select * from user 
</sql>

如果要调用上述的 SQL 代码段,可以这样写:

<select id="selectUserById" parameterType="int" resultType="User">
     <include refid="selectAllUser"/> 
            where id=#{id}
</select>

注意:上面的select标签给定义好的sql代码段添加了where条件。

6、cache

MyBatis 包含一个非常强大的,可配置和定制的缓存特性。

默认情况下缓存是未开启的,除了局部的 session 缓存,它可以提高性能,且能解决全局依赖。

要开启二级缓存,只需SQL 映射文件中添加一行:<cache/>

<cache/> 语句的效果如下:

  • 映射文件中的所有 select 语句将会被缓存
  • 映射文件中的所有 insert,update 和 delete 语句会刷新缓存
  • 缓存会使用 Least Recently Used(LRU)算法来收回
  • 缓存不会被设定的时间所清空
  • 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用
  • 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改

创建一个 FIFO 缓存让其 60s 清空一次,存储512个对象或列表引用,返回的结果只读。因此在不同线程中的调用者之间修改它们会导致引用冲突。

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

缓存可用的回收策略有:

  • LRU – 最近最少使用的:移出最近较长周期内都没有被使用的对象
  • FIFO – 先进先出:按对象进入缓存的顺序来移除
  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
  • WEAK – 弱引用:强制性地移除基于垃圾收集器状态和弱引用规则的对象

在不同的命名空间里共享同一个缓存配置或者实例。在这种情况下,可以使用 cache-ref 来引用另外一个缓存。

<cache-ref namespace="com.shiyanlou.mybatis.mapper.UserMapper"/>

本文转载自:https://www.shiyanlou.com/courses/802/labs/2801/document

共有 人打赏支持
兴趣使然的程序员
粉丝 21
博文 109
码字总数 87412
作品 0
深圳
程序员
MyBatis:快速入门实例 HelloWorld

一、简介 MyBatis是一个轻量级的持久层框架,它可以帮我们省去繁杂的JDBC操作,包括获取数据库连接、设置参数、处理结果集、事务管理等等。通过XML配置或注解,即可实现简单的完成原本复杂的...

kolbe ⋅ 2015/09/18 ⋅ 0

MyBatis入门

一 简介 mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。 mybatis可以将向preparedStatement中输入参数...

Bbigbug ⋅ 2017/11/16 ⋅ 0

Mybatis 学习系列文章

深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇) 深入浅出Mybatis系列(九)---强大的动态SQL 南轲梦 2014-11-12 16:47 深入浅出Mybatis系列(八)---mapper映射文件配置之select、r...

boonya ⋅ 2015/07/13 ⋅ 1

Mybatis 轻松入门教程

Mybatis框架 的快速入门 MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集...

yxhusmart ⋅ 2016/11/04 ⋅ 0

Spring+mybatis的一个简单例子

一、eclipse新建java项目取名SpringTest 二、导入sping,mybatis,jdbc(这里用postgresql)包到构建路径 三、在psql中建库、建表的脚本。 四、创建java类 student表对应的pojo对象 映射文件cn/...

wangxuwei ⋅ 2016/01/09 ⋅ 0

Mybatis 入门案例分享

本文分享一下,Mybatis的一些入门案例; 为什么不用JDBC方式来操作数据库,而使用类似于Mybatis的框架呢? 1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链...

故新 ⋅ 2017/11/05 ⋅ 0

MyBatis3-01之入门简介-通过Maven构建

一、概要 现在要开始自己新的学习计划了,毕设要做一个类似于物联网平台具有推送功能的那种, 这几天看看MyBatis吧,项目里打算只用这个。 二、什么是MyBatis? MyBatis 是一款优秀的持久层框...

xidiancoder ⋅ 2017/10/14 ⋅ 0

MyBatis入门学习教程 MyBatis快速入门1-8(2)

上一章:http://my.oschina.net/u/2608629/admin/edit-blog?blog=715422 上一篇MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个...

筱飞 ⋅ 2016/07/21 ⋅ 0

深入浅出MyBatis_Index

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁 ⋅ 2015/12/22 ⋅ 0

MyBatis入门学习教程 MyBatis快速入门1-8(1)

一、Mybatis介绍      MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用...

筱飞 ⋅ 2016/07/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JPA入门,配置文件的设置

<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http......

码农屌丝 ⋅ 12分钟前 ⋅ 0

Java基础——面向对象和构造器

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 静态成员介绍 为什么要有静态成员?静态成员用来...

凯哥学堂 ⋅ 14分钟前 ⋅ 0

vmware中Centos 7 linux的LVM磁盘扩容

系统是RHEL7(centos7差不多一样) 关闭系统,在vmware、设置、硬盘、扩展、输入数字大于当前系统内存、点击扩展。 开机再查看磁盘信息 fdisk -l 注意:可以看出sda磁盘增加了,但是根目录还...

gugudu ⋅ 24分钟前 ⋅ 0

JAVA线程sleep和wait方法区别

昨天面试,突然被问到sleep 和 wait的区别,一下子有点蒙,在这里记一下,以示警戒。 首先说sleep,sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过去后,cpu...

徐玉强 ⋅ 26分钟前 ⋅ 0

vuex学习--模块

随着项目复杂性增加,共享状态也越来越多。需要对转态操作进行分组,分组后在进行分组编写。学习一下module:状态管理器的模块组操作。 首先是声明: const moduleA={ state,mutations,g...

大美琴 ⋅ 28分钟前 ⋅ 0

Selenium 简单入门

安装 pip install selenium 驱动下载 https://chromedriver.storage.googleapis.com/index.html 下载最新的驱动,放入path中,可以放入Python的scripts目录下,也可以放入Chrome安装目录,并...

阿豪boy ⋅ 30分钟前 ⋅ 0

292. Nim Game - LeetCode

Question 292. Nim Game Solution 思路:试着列举一下,就能发现一个n只要不是4的倍数,就能赢。 n 是否能赢1 true2 true3 true4 false 不论删除几,对方都能一把赢5 t...

yysue ⋅ 今天 ⋅ 0

6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩

zip压缩工具 zip命令可以压缩目录和文件,-r 压缩目录。 zip使用方法 zip 1.txt.zip 1.txt //压缩文件 zip -r 123.zip 123/ //压缩目录 unzip 1.txt.zip //解压 unzip 123.zip -d /root/456...

Linux_老吴 ⋅ 今天 ⋅ 0

react-loadable使用跳坑

官方给react-loadable的定义是: A higher order component for loading components with dynamic imports. 动态路由示例 withLoadable.js import React from 'react'import Loadable fro......

pengqinmm ⋅ 今天 ⋅ 0

记录工作中遇到的坑

1、ios safari浏览器向下滚动会触发window resize事件

端木遗风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部