转自:https://blog.csdn.net/chris_mao/article/details/48811507

Mybatis的真正强大,在于她对SQL的映射,这也是她吸引人的地方。实现相同的功能,她要比直接使用JDBC省去95%的代码量。而且将 SQL语句独立在Java代码之外,为程序的修改和纠错提供了更大的灵活性,可以直接修改SQL语句,而无需重新编译Java程序。

本文将在上一篇《Mybatis系列之简单示例》的基础上,对映射文件进行详细的讨论学习。

SQL映射文件也是XML格式,其顶级元素有以下几个:

  • select - 映射sql查询语句
  • insert - 映射sql插入语句
  • update - 映射sql更新语句
  • delete - 映射sql删除语句
  • sql - 就像程序中可以复用的函数一样,这个元素下放置可以被其他语句重复引用的sql语句
  • resultMap - 用来描述如何从数据库查询结果集中来加载对象
  • cache - 给定命名空间的缓存配置
  • cache-ref - 其他命名空间缓存配置引用
下面从语句本身开始,在上一篇《Mybatis系列之简单示例》的基础上,为大家一一阐述各元素用法。

查询语句映射

查询语句,是sql中使用频率最高的语句,Mybatis中的查询语句映射也是很简单的。如:

  1. <select id="getById" parameterType="int" resultType="User">
  2. SELECT <span style="font-family: Arial, Helvetica, sans-serif;">user_name, user_password, nick_name, email, user_type_id, </span><span style="font-family: Arial, Helvetica, sans-serif;">is_valid, created_time</span>
  3. FROM sys_user WHERE user_id = #{id}
  4. </select>

这是一条被称作getById的查询,需要一个类型为int或是Integer的参数,查询返回一个User类型对象,对象的属性名称就是查询语句中的列名,属性值就是查询结果行中对应的值。


注意,上句话中斜体加粗部分,“查询语句中的列名”意味着在对查询结果进行实体映射时,使用的是查询语句中的列名进行映射的,而非数据表中的。举例说
明:select user_name .....,那么对应的实体对象属性名称就是user_name;如果在查询时使用了别名,如select
user_name as userName,那么对应的实体对象的属性名称就是userName。

通常情况下,数据表对字段命名规则使用
下划线进行分词的,而Java中却是使用驼峰式的命名规则,那么是不是意味着我们在数据表中也要使用驼峰式命名规则,或是在查询语句中都要使用别名方式
呢?其实完全不必,Mybatis早早就替我们考虑到这点的,在Mybatis核心配置文件中,只需要添加以下代码,Mybatis就可以自动的将
a_column转换为aColumn。

  1. <settings>
  2. <!-- 将数据库字段命名规则A_COLUMN转换为Java使用的驼峰式命名规则aCloumn -->
  3. <setting name="mapUnderscoreToCamelCase" value="true" />
  4. </settings>

请注意select元素中#{id}的用法,这里就是告诉Mybatis创建一个预处理语句参数,通过JDBC,这样的参数在sql中会是用一个"?"来标识,并被传递到预处理语句中。就像下面这段代码:

  1. // Similar JDBC code, NOT MyBatis…
  2. String getById = "SELECT user_name, user_password, nick_name, email, user_type_id, is_valid, created_time FROM sys_user WHERE user_id=?";
  3. PreparedStatement ps = conn.prepareStatement(getById);
  4. ps.setInt(1,id);

当然,在获得结果集后,我们还需要额外编写很多代码,将结果集的中数据映射到一个Java对象上。如果使用Mybatis,这些全部省去了,想想都很让人兴奋。(Mybatis会将#{与}之间的内容转换为预处理语句中的"?"

select语句有,有很多属性允许我们来配置,以决定每条sql语句的作用细节。

  id="getById"
parameterType="int"
parameterMap="deprecated"
resultType="User"
resultMap="userResultMap"
flushCache="false"
useCache="true"
timeout="10000"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
属性

描述
id 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
resultMap 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。
useCache 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
fetchSize STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered false。
这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。

在映射文件中定义好查询语句之后,就可以在Java代码中做如下调用:(这里插播个预告,在后面的《Mybatis系列之接口方式编程》中,我们会使用一个更简洁的方式来调用映射文件中的sql语句)

  1. @Test
  2. public void testGetById() {
  3. SqlSession session = sqlSessionFactory.openSession();
  4. try {
  5. User user;
  6. Object obj = session.selectOne("com.emerson.learning.mapping.user.getByID", 1);
  7. if (null == obj) {
  8. System.out.println("the result is null.");
  9. } else {
  10. user = (User) obj;
  11. System.out.println(user);
  12. }
  13. } finally {
  14. session.close();
  15. }
  16. }

插入语句映射

插入语句和查询语句类似,也需要定义唯一的id,指定传入参数类型。

  1. <!-- 写入新记录并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
  2. <insert id="insertUser" parameterType="User" useGeneratedKeys="true"
  3. keyProperty="userId">
  4. INSERT INTO sys_user(user_name, user_password, nick_name,
  5. user_type_id, is_valid, created_time)
  6. VALUES(#{userName},
  7. #{userPassword}, #{nickName}, #{userTypeId}, #{isValid},
  8. #{createdTime})
  9. </insert>

针对插入语句,这里有一点需要进行特别说明,那就是如何获得新插入数据的主键值。

在允许使用自增长字段做为主键的数据库中(如MSSQL,MySQL),我们只需要在insert元素中增加两个属性值即可。如:

  1. <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="userId">

将属性userGeneratedKeys设为true,并将KeyProperty属性设为数据表主键对应的实体对象属性名称。这句话有点绕,我们就以上面这条插入语句为例,数据表中主键是user_id,对应的实体对象中的属性名称是userId,所以这里我们就把userId高为KeyProperty的值。

在不允许有自增字段的数据库中(如Oracle数据库),Mybatis有另外一种方法生成数据表主键,即在insert元素内部增加一个selectKey元素,用于生成数据表主键。如

  1. <insert id="insertUser" parameterType="User">
  2. <selectKey keyProperty="userId" resultType="int" order="BEFORE">
  3. select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
  4. </selectKey>
  5. INSERT INTO sys_user(user_name, user_password, nick_name,
  6. user_type_id, is_valid, created_time)
  7. VALUES(#{userName},
  8. #{userPassword}, #{nickName}, #{userTypeId}, #{isValid},
  9. #{createdTime})
  10. </insert>
selectKey属性

属性

描述
keyProperty 匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
resultType
可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty
然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素 - 这和像 Oracle
的数据库相似,在插入语句内部可能有嵌入索引调用。
statementType
  • public void testInsertUser() {
  • SqlSession session = sqlSessionFactory.openSession();
  • try {
  • User user = new User();
  • user.setEmail("chris.mao.zb@163.com");
  • user.setNickName("Chris Mao");
  • user.setUserName("cmzb");
  • user.setIsValid(1);
  • user.setUserPassword("5f4dcc3b5aa765d61d8327deb882cf99");
  • <span class="s1" style="font-family: Arial, Helvetica, sans-serif;">int</span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">effectedRows</span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;"> = </span><span style="font-family: Arial, Helvetica, sans-serif;">session.insert("com.emerson.learning.mapping.user.insertUser", user); </span><span style="font-family: Arial, Helvetica, sans-serif;">assertEquals(</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">effectedRows</span><span style="font-family: Arial, Helvetica, sans-serif;">, 1);</span><span style="font-family: Arial, Helvetica, sans-serif;">
  • lt;/span>            System.out.println("New Id is " + user.getUserId());
  • session.commit();
  • } finally {
  • session.close();
  • }
  • }
  • 更新语句映射

    1. <update id="udpateUser" parameterType="User">
    2. UPDATE sys_user
    3. SET user_name = #{userName}, user_password = #{userPassword},nick_name = #{nickName},user_type_id = #{userTypeId},is_valid = #{isValid}
    4. WHERE user_id = #{<span style="font-family: Arial, Helvetica, sans-serif;">userId</span><span style="font-family: Arial, Helvetica, sans-serif;">}</span>
    5. </update>

    删除语句映射

    1. <delete id="deleteById" parameterType="int">
    2. DELETE FROM sys_user WHERE user_id = #{id}
    3. </delete>

    SQL

    这个元素用来定义可以重复使用的sql语句。可复用的不一定要是一个完整的sql语句,也可以是sql语句中的一部分,如字段名称等。

    以查询和插入为例,我们在查询语句中会写出好多的列名称;同样,在插入语句时也要写出这些字段名称,那么这时,我们就可以把这部分重复的sql语句单独拿出来定义。如

    1. <sql id="columns">user_name, user_password, nick_name, email, user_type_id,
    2. is_valid, created_time</sql>
    3. <!-- 根据传入的Id值,到数据库中查询记录 -->
    4. <select id="getByID" parameterType="int" resultType="User">
    5. SELECT
    6. <include refid="columns"></include>
    7. FROM sys_user WHERE user_id = #{id}
    8. </select>
    9. <!-- 按用户名进行模糊查询 -->
    10. <select id="queryByName" parameterType="User" resultType="User">
    11. SELECT
    12. <include refid="columns"></include>
    13. FROM sys_user
    14. <where>
    15. <if test="userName != null">user_name like '%' #{userName} '%'</if>
    16. </where>
    17. </select>
    18. <!-- 创建新用户,并写入到数据表中 -->
    19. <!-- 写入新记录并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
    20. <insert id="insertUser" parameterType="User" useGeneratedKeys="true"
    21. keyProperty="userId">
    22. INSERT INTO sys_user(<include refid="columns"></include>)
    23. VALUES(#{userName},
    24. #{userPassword}, #{nickName}, #{userTypeId}, #{isValid},
    25. #{createdTime})
    26. </insert>

    查询参数

    通过上面部分的讲解,细心的朋友已经发现了,Mybatis是使用#{}来定义参数的,出现在sql语句中的#{}都会为转换为预处理语句中的"?"。

    如果参数是简单类型,如int, string等,则#{}中写什么名称什么名称都可以,或是写成通用的#{_parameter}。这种写法仅限于简单数据类型。

    如果参数是一个自定义类型,则#{}中写的就是相应的属性名称,如#{userName},#{nickName}。

    Mybatis还定义了另外一种参数形式,就是${}。这个可以理解成一个占位符,她会被替找成传入的值。


    认情况下,使用#{}格式的语法会导致Mybatis创建预处理语句属性,并安全地设置传入值(比如会自动对字符型数据两边加上引号等)。这样做更安全、
    更迅速,也是道选做法。不过有时只是想直接在sql语句中原样不变地插入一个字符串,比如ORDER BY  ${COLUMN}。

    查询结果集

    ResultMap是Mybatis最重要、最强大,也是相对最复杂的一个元素。这里就不多做说明,待后续文章《Mybatis系列之一对多关系》时再做具体讲解。

    缓存

    Mybatis包含了一个很强大的缓存特性,可以非常方便地配置和使用。默认情况下,缓存功能是没有开启的。要想使用缓存只需要sql映射文件中加入cache元素即可。
     
    1. <cache />

    这个简单语句效果如下:

    • 映射文件中所有的select语句都将会被缓存
    • 映射文件中所有的insert / update / delete语句会刷新缓存
    • 缓存默认使用LRU最近最少使用算法来回收
    • 根据时间表,缓存不会以作何时间顺序来刷新
    • 缓存最多会存储列表集合或是对象的1024个引用
    • 缓存被视为可读、写缓存,这意味着对象检索不是共享的,且可以安全地被调用者修改,而不干拢其他调用过或线程所做的潜在修改。
    所有这些属性,都可以通过cache元素的属性进行修改配置。如
    1. <cache
    2. eviction="FIFO"
    3. flushInterval="60000"
    4. size="512"
    5. readOnly="true"/>

    这个算法将缓存的回收策略改为了先进先出,并且每隔60秒刷新一次,最大缓存对象引用数量为512,且返回的对象是只读的,因此在不同线程中的调用者修改它们会导致冲突。

    Mybatis中回收策略有以下几种:
    • LRU - 最近最少使用的:移除最长时间不被使用的对象
    • FIFO - 先进先出:按对象进入缓存的时间顺序来移除
    • SOFT - 软引用:移除基于垃圾回收器状态和软引用规则的对象
    • WEAK - 弱引用:更积极地移除基于垃圾回收器状态和弱引用规则的对象
    flushInterval,刷新间隔,可以被设置为任意的正整数,代表每隔多少毫秒进行一次刷新动作。默认情奖品是不设置,也就是没有刷新间隔,缓存仅仅在有sql语句被调用时刷新。
    size,最大引用数量,可以被设置为任意的正整数。默认是1024
    readOnly,
    只读属性,可以被设为true 或
    false。只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势。可读写缓存则返回对象的拷贝,这样在
    性能上会有一些损失,但是安全。Mybatis默认是false。

    名称空间

    每个sql映射文件的要元素中,都需要指定一个名称空间,用以确保每个映射语句的id属性不会重复。如

    1. <mapper namespace="com.emerson.learning.mapping.user">

    在Java代码中引用某个sql映射时,使用的亦时含有名称空间的全路径。如

    1. session.update("com.emerson.learning.mapping.user.udpateUser", user);

    代码示例

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. <mapper namespace="com.emerson.learning.mapping.user">
    5. <sql id="columns">user_name, user_password, nick_name, email, user_type_id,
    6. is_valid, created_time</sql>
    7. <!-- 根据传入的Id值,到数据库中查询记录 -->
    8. <select id="getByID" parameterType="int" resultType="User">
    9. SELECT
    10. <include refid="columns"></include>
    11. FROM sys_user WHERE user_id = #{id}
    12. </select>
    13. <!-- 按用户名进行模糊查询 -->
    14. <select id="queryByName" parameterType="User" resultType="User">
    15. SELECT
    16. <include refid="columns"></include>
    17. FROM sys_user
    18. <where>
    19. <if test="userName != null">user_name like '%' #{userName} '%'</if>
    20. </where>
    21. </select>
    22. <!-- 创建新用户,并写入到数据表中 -->
    23. <!-- 写入新记录并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
    24. <insert id="insertUser" parameterType="User" useGeneratedKeys="true"
    25. keyProperty="userId">
    26. INSERT INTO sys_user(<include refid="columns"></include>)
    27. VALUES(#{userName},
    28. #{userPassword}, #{nickName}, #{userTypeId}, #{isValid},
    29. #{createdTime})
    30. </insert>
    31. <!-- 更新用户信息,并写回到数据表中 -->
    32. <update id="udpateUser" parameterType="User">
    33. UPDATE sys_user
    34. <set>
    35. <if test="userName != null">user_name = #{userName},</if>
    36. <if test="userPassword != null">user_password = #{userPassword},</if>
    37. <if test="nickName != null">nick_name = #{nickName},</if>
    38. <if test="userTypeId != null">user_type_id = #{userTypeId},</if>
    39. <if test="isValid != null">is_valid = #{isValid}</if>
    40. </set>
    41. WHERE user_id = #{userId}
    42. </update>
    43. <!-- 根据传入的Id值,删除单条记录 -->
    44. <delete id="deleteById" parameterType="int">
    45. DELETE FROM sys_user WHERE
    46. user_id = #{id}
    47. </delete>
    48. <!-- 根据传入的Id值列表,删除多条记录 -->
    49. <delete id="deleteBatch" parameterType="java.util.List">
    50. DELETE FROM sys_user WHERE user_id in
    51. <foreach collection="list" item="item" index="index" open="("
    52. close=")" separator=",">
    53. #{item}
    54. </foreach>
    55. </delete>
    56. </mapper>

    结束语

    至此,我们把Mybatis中sql映射文件的元素都已向大家介绍了一遍(除了ResultMap,这个留在后续的文章中详细讲解)。在下一篇文章《Mybatis系列(五)动态SQL》中,我们继续为大家讲解用于定义动态SQL的映射标签,静请期待!

Mybatis系列(四)映射文件的更多相关文章

  1. Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件

    封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...

  2. MyBatis系列四 之 智能标签进行查询语句的拼接

    MyBatis系列四 之 智能标签进行查询语句的拼接 使用Foreach进行多条件查询 1.1 foreach使用数组进行多条件查询 在MyBatis的映射文件中进行如下配置 <!--根据数组进 ...

  3. Mybatis 系列2-配置文件

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  4. Mybatis(二) SQL映射文件

    SQL映射文件 单条件查询 1. 在UserMapper接口添加抽象方法 //根据用户名模糊查询 List<User> getUserListByName(); 2. 在UserMappe ...

  5. Mybatis的XML映射文件(四)

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

  6. mybatis Mapper XML 映射文件

    传送门:mybatis官方文档 Mapper XML 文件详解 一. 数据查询语句 1. select <select id="selectPerson" parameter ...

  7. Mybatis框架基于映射文件和配置文件的方式,实现增删改查,可以打印日志信息

    首先在lib下导入: 与打印日志信息有关的架包 log4j-1.2.16.jar mybatis架包:mybatis-3.1.1.jar 连接数据库的架包:mysql-connector-java-5 ...

  8. 初始MyBatis、SQL映射文件

    MyBatis入门 1.MyBatis前身是iBatis,是Apache的一个开源项目,2010年这个项目迁移到了Google Code,改名为MyBatis,2013年迁移到GitHub.是一个基于 ...

  9. MyBatis 的 XML 映射文件使用说明

    简介 文档参考地址:http://www.mybatis.org/mybatis-3/zh/index.html MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器 ...

  10. mybatis教程3(映射文件)

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

随机推荐

  1. HTML 中 id与name 区别

    一个name可以同时对应多个控件,比如checkbox和radio而id必须是全文档中唯一的 id的用途1) id是HTML元素的Identity,主要是在客户端脚本里用.2) label与form控 ...

  2. 条款11:记得在operator=中处理自赋值的情况。

    本来的版本是这样的: Widget & Widget::operator=(Widget rhs) { delete pb;//这里可能直接将rhs的pb删除了 pb = new (*rhs. ...

  3. switch遇到0的问题

    你是否经常有switch来代替if else?是否因为使用了switch,提高代码的执行效率而庆幸?好吧,你和我一样,但也许你没有遇到下面的问题. 这个小程序,会输出什么呢?会是'00'么?   结果 ...

  4. linux 权限之所有者所属组

    linux 如何改变文件属性与权限 我们知道档案权限对于一个系统的安全重要性,也知道档案的权限对于使用者与群组的相关性, 那如何修改一个档案的属性与权限呢? 我们这里介绍几个常用于群组.拥有者.各种身 ...

  5. MySQL免安装版安装配置、修改密码

    一:MySQL的下载安装 1.1 下载 我下载的是 ZIP Archive 版的,win7 64位的机器支持使用,而且相对而言,简单.干净. 首先,进入MySQL的官方网址,依次点击Downloads ...

  6. Centos7下命令笔记-ls

    ls命令大概是linux下最常用的命令之一,ls是list的缩写.因为linux目录或者文件记录的信息实在太多,所以默认ls只显示非隐藏的目录以及文件名.ls直接执行不加参数时显示本目录下的档案名. ...

  7. fn project 私有镜像发布

    1. 说明 fnproject 默认的docker registry 是 dockerhub 对于企业应用还是不太方便的 还好系统系统了配置参数方便我们进行配置,与开源harbor 进行集成 2. 使 ...

  8. 区域存储网络(SAN)与 网络直接存储(NAS)

    随着互联网及网络应用的飞速发展,数据信息存储系统所需处理的数据类型也呈爆炸性增长,这使数据信息存储系统面临前所未有的挑战.附加式网络存储装置(Network Attached Storage,缩写为N ...

  9. maven搭建

    http://blog.csdn.net/zhshulin/article/details/30779873 http://blog.csdn.net/zhshulin/article/details ...

  10. his移植问题

    报错信息 权限不够未截图 注意修改uploads文件权限chmod 777 uploads 修改域名 参照dxtzy项目,sourcetree备注