文章目录
1 mybatis的mapper实用详解
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。动态sql和映射
顶级元素mapper有一个参数值namespace表示该映射配置文件的对应的接口位置
<mapper namespace="com.tadpole.itemorder.ItemOrderMapper">
</mapper>
顶级元素mapper下的子元素
- insert – 映射插入语句。
- update – 映射更新语句。
- delete – 映射删除语句。
- select – 映射查询语句。
- cache – 该命名空间的缓存配置。
- cache-ref – 引用其它命名空间的缓存配置。
- resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
- sql – 可被其它语句引用的可重用语句块。
1.1 insert, update 和 delete 修改语句
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句,所以mapper接口的方法是不能重载的。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键,默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
<insert
id="insertAuthor"
parameterType="com.tadpole.itemorder.ItemOrder"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"></insert>
<update
id="updateAuthor"
parameterType="com.tadpole.itemorder.ItemOrder"
flushCache="true"
statementType="PREPARED"
timeout="20"></update>
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"></delete>
1.2 select查询语句
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句,所以mapper接口的方法是不能重载的。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
resultType | 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。 |
resultMap | 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。 |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
fetchSize | 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false。 |
resultSets | 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。 |
select的子元素中有selectKey ,不建议使用selectKey
支持动态sql,的循环语句foreach
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password})
</foreach>
1.3 sql
该元素可以用来定义重用的sql片段,使用include引入到对应的语句中
<sql id="orderPayColumns">order_id orderId, orderName,price,${}</sql>
<select id="selectById" resultMap="itemOrder">
select <include refid="orderPayColumns"></include> from item_order where id = #{id}
</select>
1.4 resultMap 映射集合
- constructor - 用于在实例化类时,注入结果到构造方法中
- idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
- arg - 将被注入到构造方法的一个普通结果
- id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
- result – 注入到字段或 JavaBean 属性的普通结果
- association – 一个复杂类型的关联;许多结果将包装成这种类型
- 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
- collection – 一个复杂类型的集合
- 嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用
- discriminator – 使用结果值来决定使用哪个 resultMap
- case – 基于某些值的结果映射
- 嵌套结果映射 – case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
- case – 基于某些值的结果映射
下面是 id 和 result 元素的属性。
属性 | 描述 |
---|---|
column | 数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。 |
javaType | 一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。 |
jdbcType | JDBC 类型,所支持的 JDBC 类型参见这个表格之前的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能存在空值的列指定这个类型。 |
typeHandler | 我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。 |
select | 用于加载复杂类型属性的映射语句的 ID,它会从 column 属性中指定的列检索数据,作为参数传递给此 select 语句。具体请参考关联元素。 |
resultMap | 结果映射的 ID,可以将嵌套的结果集映射到一个合适的对象树中。 它可以作为使用额外 select 语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。这样的 ResultSet 将会将包含重复或部分数据重复的结果集。为了将结果集正确地映射到嵌套的对象树中,MyBatis 允许你 “串联”结果映射,以便解决嵌套结果集的问题。想了解更多内容,请参考下面的关联元素。 |
name | 构造方法形参的名字 |
1.5 cache 缓存
<cache/>
缓存只作用于 cache 标签所在的映射文件中的语句,基本上就是这样。这个简单语句的效果如下:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
可用的清除策略有:
- LRU – 最近最少使用:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
- WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
参数名 | 说明 |
---|---|
type | 指定缓存(cache)接口的实现类型,当需要和ehcache整合时更改该参数值即可。 |
flushInterval | 刷新间隔。可被设置为任意的正整数,单位毫秒。默认不设置。 |
size | 引用数目。可被设置为任意正整数,缓存的对象数目等于运行环境的可用内存资源数目。默认是1024。 |
readOnly | 只读,true或false。只读的缓存会给所有的调用者返回缓存对象的相同实例。默认是false。 |
eviction | 缓存收回策略。LRU(最近最少使用的),FIFO(先进先出),SOFT( 软引用),WEAK( 弱引用)。默认是 LRU。 |
cache的属性有type
- 如果要实现自定义缓存的话,就实现type 属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口
1.6 cache-ref
对某一命名空间的语句,只会使用该命名空间的缓存进行缓存或刷新。 但你可能会想要在多个命名空间中共享相同的缓存配置和实例。要实现这种需求,你可以使用 cache-ref 元素来引用另一个缓存
1.7 动态sql
借助功能强大的基于 OGNL 的表达式
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
1.7.1 if
<select id="selectCountAll"
resultType="int">
SELECT count(*) FROM item_order
WHERE id > 0
<if test="index != null">
AND index > #{index}
</if>
</select>
1.7.2 choose、when、otherwise
<select id="selectCountAll"
resultType="int">
SELECT count(*) FROM item_order
WHERE id > 0
<choose>
<when test="name != null">
AND name like #{name}
</when>
<when test=" price != null">
AND price = #{price}
</when>
<otherwise>
AND price = 20
</otherwise>
</choose>
</select>
1.7.3 trim、where、set
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT count(*) FROM item_order
<where>
<if test="name != null">
name = #{name}
</if>
<if test="price != null">
AND price = #{price}
</if>
</where>
</select>
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号
<update id="updateAuthorIfNecessary">
update item_order
<set>
<if test="name != null">name=#{username},</if>
<if test="price != null">price=#{password}</if>
</set>
where id=#{id}
</update>
trim 可以实现和set一样的功能,prefix开头的指定内容,suffixOverrides多余的额外内容
<trim prefix="SET" suffixOverrides=",">
...
</trim>
1.7.4 foreach
<select id="selectByIds" resultType="com.tadpole.itemOrder.ItemOrder">
SELECT *
FROM item_order
WHERE id in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
1.7.5 script
要在带注解的映射器接口类中使用动态 SQL,可以使用 script 元素。比如
@Update({"<script>",
"update item_order",
" <set>",
" <if test='name != null'>name=#{name},</if>",
" <if test='price != null'>price=#{price}</if>",
" </set>",
"where id=#{id}",
"</script>"})
void selectByName(ItemOrder itemOrder);
1.7.6 bind
bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文
<select id="selectBlogsLike" resultType="com.tadpole.itemOrder.ItemOrder">
<bind name="pattern" value="'%' + itemOrder.getName() + '%'" />
SELECT * FROM item_order
WHERE name LIKE #{pattern}
</select>