SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

  • cache – 给定命名空间的缓存配置。
  • cache-ref – 其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

select

查询

<select id="selectPerson" parameterType="int" resultType="hashmap">SELECT * FROM PERSON WHERE ID = #{id}
</select>

下面就是 insert,update 和 delete 语句的示例

<insert id="insertAuthor">insert into Author (id,username,password,email,bio)values (#{id},#{username},#{password},#{email},#{bio})
</insert><update id="updateAuthor">update Author setusername = #{username},password = #{password},email = #{email},bio = #{bio}where id = #{id}
</update><delete id="deleteAuthor">delete from Author where id = #{id}
</delete>

在插入语句里面有一些额外的属性和子元素用来处理主键的生成,有多种生成方式。

如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK了

<insert id="insertAuthor" useGeneratedKeys="true"keyProperty="id">insert into Author (username,password,email,bio)values (#{username},#{password},#{email},#{bio})
</insert>

对不支持自动生成主键的JDBC驱动,Mybatis有另外一种生成主键。

<insert id="insertAuthor"><selectKey keyProperty="id" resultType="int" order="BEFORE">select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1</selectKey>insert into Author(id, username, password, email,bio, favourite_section)values(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>

在上面的示例中,selectKey 元素将会首先运行,Author 的 id 会被设置,然后插入语句会被调用。

sql

<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

这个元素可以被用来定义重用的sql代码段。可以被包含在其他语句中。

<select id="selectUsers" resultType="map">select<include refid="userColumns"><property name="alias" value="t1"/></include><include refid="userColumns"><property name="alias" value="t2"/></include>from some_table t1cross join some_table t2
</select>

属性值也可以被用在 include 元素的 refid 属性里<include refid="${include_target}"/>或include内部语句中${prefix}Table

参数(Parameters)

<insert id="insertUser" parameterType="User">insert into users (id, username, password)values (#{id}, #{username}, #{password})
</insert>

如果User类型的参数对象传递到了语句中,id、username 和 password 属性将会被查找。

大多时候你只须简单地指定属性名,其他的事情 MyBatis 会自己去推断,顶多要为可能为空的列指定 jdbcType。

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}

更多选项设置:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Parameters

字符串替换

默认情况,使用 #{} 会导致PreparedStatement参数创建,并安全设置参数。首选!
有时想插入一个不转义的字符串,如:

ORDER BY ${columnName}

注意:用这种方式不安全,可能导致sql注入,要么不允许用户输入这些字段,要么自行转义验证。

Result Maps

resultMap 元素是 MyBatis 中最重要最强大的元素。用来支持程序使用 JavaBean 或 POJO(Plain Old Java Objects,普通 Java 对象)作为领域模型。

例如下面配置映射到User实体中

<select id="selectUsers" resultType="com.someapp.model.User">select id, username, hashedPasswordfrom some_tablewhere id = #{id}
</select>

类型别名可以帮助你不用输入类的完全限定名

<!-- In mybatis-config.xml file -->
<typeAlias type="com.someapp.model.User" alias="User"/><!-- In SQL Mapping XML file -->
<select id="selectUsers" resultType="User">select id, username, hashedPasswordfrom some_tablewhere id = #{id}
</select>

Mybatis会创建一个ResultMap,映射到javaBean中。如果没有匹配上,可以再select语句中使用别名

<select id="selectUsers" resultType="User">selectuser_id             as "id",user_name           as "userName",hashed_password     as "hashedPassword"from some_tablewhere id = #{id}
</select>

下面是另一种方式来实现映射。

<resultMap id="userResultMap" type="User"><id property="id" column="user_id" /><result property="username" column="user_name"/><result property="password" column="hashed_password"/>
</resultMap>

引用它的语句时使用resultMap属性(我们去掉了resultType属性)。

<select id="selectUsers" resultMap="userResultMap">select user_id, user_name, hashed_passwordfrom some_tablewhere id = #{id}
</select>

总结:resultMap可以用来解决数据库列名与属性没有匹配的问题。如果足够了解它,就不需要显示配置它。

高级结果映射

<!-- 超复杂的 Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog"><constructor><idArg column="blog_id" javaType="int"/></constructor><result property="title" column="blog_title"/><association property="author" javaType="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/><result property="password" column="author_password"/><result property="email" column="author_email"/><result property="bio" column="author_bio"/><result property="favouriteSection" column="author_favourite_section"/></association><collection property="posts" ofType="Post"><id property="id" column="post_id"/><result property="subject" column="post_subject"/><association property="author" javaType="Author"/><collection property="comments" ofType="Comment"><id property="id" column="comment_id"/></collection><collection property="tags" ofType="Tag" ><id property="id" column="tag_id"/></collection><discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/></discriminator></collection>
</resultMap>

解析:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps

构造方法

public class User {//...public User(Integer id, String username, int age) {//...}
//...
}

将结果注入构造方法,Mybatis需要通过某种方式定位相应构造方法。constructor 元素就是为此而生的。

<constructor><idArg column="id" javaType="int"/><arg column="username" javaType="String"/><arg column="age" javaType="_int"/>
</constructor>

从版本 3.4.3 开始,可以在指定参数名称的前提下,以任意顺序编写 arg 元素。可以添加@Param注解做到

<constructor><idArg column="id" javaType="int" name="id" /> <!--name是javaBean中属性,column是数据库中字段--><arg column="age" javaType="_int" name="age" /><arg column="username" javaType="String" name="username" />
</constructor>

如果类中存在名称和类型相同的属性,那么可以省略 javaType 。

关联

<association property="author" column="blog_author_id" javaType="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/>
</association>

关联的嵌套查询

<resultMap id="blogResult" type="Blog"><association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap><select id="selectBlog" resultMap="blogResult">SELECT * FROM BLOG WHERE ID = #{id}
</select><select id="selectAuthor" resultType="Author">SELECT * FROM AUTHOR WHERE ID = #{id}
</select>

我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的 author 属性。
其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单,但是对于大型数据集合和列表表现不好,原因是我们熟悉的“N+1 查询问题”

  • 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
  • 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

Mybatis能延时加载是好事,但是加载完后立即调用所有延迟加载,就很糟糕。

有另外一种方法。

关联的嵌套结果

<select id="selectBlog" resultMap="blogResult">selectB.id            as blog_id,B.title         as blog_title,B.author_id     as blog_author_id,A.id            as author_id,A.username      as author_username,A.password      as author_password,A.email         as author_email,A.bio           as author_biofrom Blog B left outer join Author A on B.author_id = A.idwhere B.id = #{id}
</select>

注意这个联合查询, 使用唯一而且清晰的名字来重命名。 使映射非常简单。

<resultMap id="blogResult" type="Blog"><id property="id" column="blog_id" /><result property="title" column="blog_title"/><association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap><resultMap id="authorResult" type="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/><result property="password" column="author_password"/><result property="email" column="author_email"/><result property="bio" column="author_bio"/>
</resultMap>

在上面,authorResult 用来加载作者实例。现在,上面的示例用了外部的结果映射元素来映射关联。这使得 Author 结果映射可以 重用

非常重要: id元素在嵌套结果映射中扮演着非 常重要的角色。 不指定唯一标志属性,会有严重的性能问题。

如果不需要映射到单独的结果映射中,也可以嵌套结果映射。

<resultMap id="blogResult" type="Blog"><id property="id" column="blog_id" /><result property="title" column="blog_title"/><association property="author" javaType="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/><result property="password" column="author_password"/><result property="email" column="author_email"/><result property="bio" column="author_bio"/></association>
</resultMap>

集合

<collection property="posts" ofType="domain.blog.Post"><id property="id" column="post_id"/><result property="subject" column="post_subject"/><result property="body" column="post_body"/>
</collection>

和关联相同,不同处:

private List<Post> posts;

集合的嵌套查询

首先,让我们看看使用嵌套查询来为博客加载文章。

<resultMap id="blogResult" type="Blog"><collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap><select id="selectBlog" resultMap="blogResult">SELECT * FROM BLOG WHERE ID = #{id}
</select><select id="selectPostsForBlog" resultType="Post">SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

关注这段

<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>

读作:“在Post类型的ArrayList中的posts的集合”。

集合的嵌套结果

至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性
详细介绍:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps
你的应用在找到最佳方法前要一直进行的单元测试和性 能测试。

鉴别器

  <discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/></discriminator>

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

自动映射

如果数据库字段名和javaBean属性名不一致,要将 mapUnderscoreToCamelCase设置为true

例如:

<select id="selectUsers" resultMap="userResultMap">selectuser_id             as "id",user_name           as "userName",hashed_passwordfrom some_tablewhere id = #{id}
</select>
<resultMap id="userResultMap" type="User"><result property="password" column="hashed_password"/>
</resultMap>

上面的例子中,id和userName和javaBean中属性一致,被自动映射了。而hashed_password在resultMap中映射了字段和属性,所以在结果中也能取到值。

有三种自动映射等级:

  • NONE - 禁用自动映射。仅设置手动映射属性。
  • PARTIAL(默认) - 将自动映射结果除了那些有内部定义内嵌结果映射的(joins).
  • FULL - 自动映射所有。

缓存

一级缓存是SQLSession级别的缓存,换出的数据只在SQLSession内有效。
二级缓存是mapper级别的缓存,同一个namespace公用这个缓存,所以对SQLSession是共享的

一级缓存

1.第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来

2.第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率

注意事项:

  • 如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前SqlSession缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
  • 当一个SqlSession结束后那么他里面的一级缓存也就不存在了,mybatis默认是开启一级缓存,不需要配置
  • mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。例如:-1242243203:1146242777:winclpt.bean.userMapper.getUser:0:2147483647:select * from user where id=?:19

二级缓存

二级缓存是mapper级别的缓存。也就是同一个namespace的mapper.xml,当多个SQLSession使用同一个mapper操作数据库,得到的数据会缓存在同一个二级缓存中。

具体流程:
  1.当一个sqlseesion执行了一次select后,在关闭此session的时候,会将查询结果缓存到二级缓存
  2.当另一个sqlsession执行select时,首先会在他自己的一级缓存中找,如果没找到,就回去二级缓存中找,找到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能

注意事项:
   如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前mapper缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读。

开启二级缓存:
confg.xml

<settings><setting name="cacheEnabled" value="true"/>默认是false:关闭二级缓存
<settings>

userMapper.xml

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/> 当前mapper下所有语句开启二级缓存

配置了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,返回的对象是只读。
若想禁用某select语句的二级缓存,添加userCache="false"

<select id="getCountByName" parameterType="java.util.Map" resultType="INTEGER" statementType="CALLABLE" useCache="false">

可用的收回策略有:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

使用自定义缓存

Mybatis3 (2)xml映射文件相关推荐

  1. Mybatis学习--Mapper.xml映射文件

    简介 Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. 映射文件中有很多属性,常用的就是parameterType(输入类型 ...

  2. Mapper.xml映射文件---Mybatis学习笔记(八)

    Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. parameterType(输入类型) 1.#{}与${} #{}实现的是 ...

  3. Mybatis官方文档中的(XML映射文件)模块(半途凉了)

    Mybatis官方文档中的(XML映射文件)模块(半途凉了) 一.XML映射器属性的介绍 Mybatis的真正强大之处在于它的语句映射.他即可以自动的映射数据库中的字段和对象的属性. SQL映射文件有 ...

  4. binding.BindingException: Invalid bound statement (not found): xxx → dao接口和mapper.xml映射文件绑定异常

    在进行mybatis开发的时候, 可能会遇到org.apache.ibatis.binding.BindingException: Invalid bound statement (not found ...

  5. mybatis insert返回主键_MyBatis官方文档XML 映射文件

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

  6. myBatis的xml映射文件中传入list集合与数组做条件

    mybatis的xml映射文件中传入list集合与数组做条件 1.传list集合参数 1.1sql映射: <select id="queryDeptListByBankLevelAnd ...

  7. MyBatis 学习(七):深入 Mapper XML映射文件

    深入 Mapper XML映射文件 一.Mapper XML映射文件 二.select 查询语句 三.insert.update 和 delete 四.sql 元素 五.参数(Parameters) ...

  8. java实体类没有映射文件_MyBatis自动生成实体类、DAO和XML映射文件,并去掉实体类中的getter和setter方法...

    今天花了3个多小时搞定了这个事情,写个Blog记录一下,先看一下最终生成的实体类吧. packagecom.mybatis.pojo;importlombok.AllArgsConstructor;i ...

  9. MyBatis官方文档-XML 映射文件

    最近更新: 15 七月 2019|版本: 3.5.2 文章目录 XML 映射文件 insert, update 和 delete sql 结果映射 高级结果映射 结果映射(resultMap) id ...

  10. MyBatis学习之映射器Mapper(接口映射器+xml映射文件)

    Table of Contents 01 MyBatis映射器: 1.1 接口映射器+xml映射器 1.2 接口映射器+注解 02 接口映射器+xml映射器  方式 2.1 mybatis配置文件 引 ...

最新文章

  1. 什么是方向图乘积定理_课本上没有,但十分好用的初中数学定理公式
  2. 从传递函数到差分方程的转换
  3. php百度编辑器精简版,开源web编辑器|百度编辑器ueditor下载1.4.3.4php版 下载_久友软件下载...
  4. could not perform addBatch
  5. 2012年1月份第2周51Aspx源码发布详情
  6. python如果选择不在列表里_Python-list.remove(x)x不在列表中
  7. Altium Designer20原理图库放置引脚报错解决方案
  8. php二维数组引用变量,PHP二维数组的引用赋值容易犯的错误
  9. 大学数学实验习题--统计推断 03(附答案)
  10. 单片机广告灯实验总结_单片机流水灯实验总结精选 .doc
  11. 《软件设计师》复习总结
  12. html中怎么设置栅格,[CSS] 栅格化布局
  13. java找中点_java中点是什么意思
  14. 2010-05-20 代码复用、使用率情况分析
  15. csgo删除机器人_csgo1v1去除机器人 | 手游网游页游攻略大全
  16. 链表的快速排序及冒泡排序
  17. [C语言]插入字符A:用字符数组作函数参数,编程实现在字符串每个字符间插入一个空格的功能。
  18. Docker创建运行多个mysql容器
  19. 论文水记|How to Train Triplet Networks with 100K Identities?
  20. 2021-11-29 拿到第一个badger

热门文章

  1. CF750F. New Year and Finding Roots
  2. Link-Cut Tree
  3. 2020 ICPC NAC
  4. P4878 [USACO05DEC]Layout G
  5. 洛谷P3270:成绩比较(容斥、组合数学)
  6. P5048-[Ynoi2019 模拟赛]Yuno loves sqrt technology III【分块】
  7. jzoj4788-[NOIP2016提高A组模拟9.17]序列【差分,贪心】
  8. POJ2182-Lost Cows【树状数组,二分】
  9. 纪中B组模拟赛总结(2020.2.09)
  10. 架构师必须掌握的 10 条设计原则