Mybatis SQL映射文件讲解
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
- cache – 配置给定命名空间的缓存。
- cache-ref – 从其他命名空间引用缓存配置。
- resultMap – 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加 载你的对象。
- parameterMap – 已经被废弃了!老式风格的参数映射。内联参数是首选,这个元 素可能在将来被移除。
- sql – 可以重用的 SQL 块,也可以被其他语句引用。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
select
查询语句是使用 MyBatis 时最常用的元素之一,对简单类别的查询元素是非常简单的。比如:
<select id="selectPerson" parameterType="int" resultType="java.lang.Hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
- 1
- 2
- 3
这个语句被称作 selectPerson, 使用一个 int (或 Integer) 类型的参数, 并返回一个 HashMap 类型的对象,其中的键是列名,值是列对应的值。
这就告诉 MyBatis 创建一个预处理语句参数。 使用 JDBC, 这样的一个参数在 SQL 中会 由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:
// Similar JDBC code, NOT MyBatis…
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
- 1
- 2
- 3
- 4
默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并以它为背景设 置安全的值(比如?) 。这样做很安全,很迅速也是首选做法,有时你只是想直接在 SQL 语 句中插入一个不改变的字符串。比如,像 ORDER BY,你可以这样来使用:
ORDER BY ${columnName}
- 1
这里 MyBatis 不会修改或转义字符串,接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会 导致潜在的 SQL 注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检 查。
select 元素有很多属性允许你配置,来决定每条语句的作用细节。
- id
在命名空间中唯一的标识符,可以被用来引用这条语句。 - parameterType
将会传入这条语句的参数类的完全限定名或别名,参数可以是基本数据类型,也可以是一个对象。 parameterMap
这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数 映射和 parameterType 属性。resultType
从这条语句中返回的期望类型的类的完全限定名或别名。注意集 合情形,那应该是集合可以包含的类型,而不能是集合本身。使 用 resultType 或 resultMap,但不能同时使用。- resultMap
命名引用外部的 resultMap。 返回 map 是 MyBatis 最具力量的特性, 对其有一个很好的理解的话, 许多复杂映射的情形就能被解决了。通俗来讲pojo属性与表中列名不区分大小写情况下相同使用resultType,不同使用resultMap。 - flushCache
将其设置为 true,不论语句什么时候被调用,都会导致缓存被 清空。默认值:false。 - useCache
将其设置为 true, 将会导致本条语句的结果被缓存。 默认值: true。 - timeout
这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的 最大等待值。默认不设置(驱动自行处理) - fetchSize
这是暗示驱动程序每次批量返回的结果行数。默认不设置(驱动 自行处理)。 - statementType
STATEMENT,PREPARED 或 CALLABLE 的一种。 这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。 默认值:PREPARED。
insert, update and delete
数据变更语句 insert,update 和 delete 在它们的实现中非常相似:
<insert id="insertAuthor" parameterType="domain.blog.Author">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor" parameterType="domain.blog.Author">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor" parameterType="int">
delete from Author where id = #{id}
</delete>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
sql
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。比如:
<sql id="userColumns">
id,username,password
</sql>
- 1
- 2
- 3
这个 SQL 片段可以被包含在其他语句中,例如:
<select id="selectUsers" parameterType="int" resultType="hashmap">
select <include refid="userColumns"/>
from some_table
where id = #{id}
</select>
- 1
- 2
- 3
- 4
- 5
ResultMap
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="username"/>
<result property="password" column="password"/>
</resultMap>
- 1
- 2
- 3
- 4
- 5
引用它的语句使用 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:
<select id="selectUsers" parameterType="int" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
- 1
- 2
- 3
- 4
- 5
ResultMap功能是非常强大的,里面还涉及到各种嵌套查询,这块会单独讨论。
缓存
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
<cache/>
- 1
字面上看就是这样。这个简单语句的效果如下:
•映射语句文件中的所有 select 语句将会被缓存。
•映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
•缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
•根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
•缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
•缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
所有的这些属性都可以通过缓存元素的属性来修改。比如:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
- 1
- 2
- 3
- 4
- 5
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。
可用的收回策略有:
•LRU – 最近最少使用的:移除最长时间不被使用的对象。
•FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
•SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
•WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。
参照缓存
这个特殊命名空间的唯一缓存会被使用或者刷新相同命名空间内 的语句。也许将来的某个时候,你会想在命名空间中共享相同的缓存配置和实例。在这样的 情况下你可以使用 cache-ref 元素来引用另外一个缓存。
<cache-ref namespace="com.someone.application.data.SomeMapper"/>