Mybatis 应用
1 Mybatis 入门与编码流程
2 mapper代理开发方式
3 全局配置文件
4 输入映射和输出映射
5 关联查询
6 延迟加载
7 动态SQL
8 Mybatis缓存
Mybatis 动态SQL
一、动态SQL介绍
动态SQL的思想:就是使用不同的动态SQL标签去完成字符串的拼接处理、循环判断。
解决的问题是:
1、 在映射文件中,会编写很多有重叠部分的SQL语句,比如SELECT语句和WHERE语句等这些重叠语句,该如何处理。
2、SQL语句中的where条件有多个,但是页面只传递过来一个条件参数,此时会发生问题。
二、 标签功能说明
2.1 if标签
查询条件是由页面传入,页面中的查询条件可能输入用户名称,也可能不输入用户名称。
<select id="findUserList" parameterType="queryVo" resultType="user">SELECT * FROM user where 1=1
<if test="user != null">
<if test="user.username != null and user.username != ''">AND username like '%${user.username}%'</if>
</if>
</select>
2.2 where标签
上边的sql中的1=1,虽然可以保证sql语句的完整性:但是存在性能问题。(索引相关?)Mybatis提供where标签解决该问题。 where 遇到第一个and,会将第一个and 去掉。
<select id="findUserList" parameterType="queryVo" resultType="user">SELECT * FROM user <!-- where标签会处理它后面的第一个and -->
<where>
<if test="user != null">
<if test="user.username != null and user.username != ''">AND username like '%${user.username}%'</if>
</if>
</where>
</select>
2.3 sql片段
在映射文件中可使用sql标签将重复的sql提取出来,然后使用include标签引用即可,最终达到sql重用的目的,具体实现如下:
1、将where条件抽取出来:
<sql id="query_user_where">
<if test="user != null">
<if test="user.username != null and user.username != ''">AND username like '%${user.username}%'</if>
</if>
</sql>
2、使用include引用
<!-- 使用包装类型查询用户 使用ognl从对象中取属性值,如果是包装对象可以使用.操作符来 取内容部的属性 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
SELECT * FROM user
<!-- where标签会处理它后面的第一个and -->
<where>
<include refid="query_user_where"></include>
</where>
</select>
注意:
1、如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段”/>
2.4 foreach
综合查询时,传入多个id查询用户信息,用下边两个sql实现:
SELECT * FROM USER WHERE username LIKE '%老郭%' AND (id =1 OR id =10 OR id=16)
SELECT * FROM USER WHERE username LIKE '%老郭%' AND id IN (1,10,16)
2.4.1 代码实现
在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法。保存查询条件的参数。
public class QueryVo {
private User user;
private List<Integer> ids;
}
<sql id="query_user_where">
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
</if>
<if test="ids != null and ids.size() > 0">
<!-- collection:指定输入的集合参数的参数名称 -->
<!-- item:声明集合参数中的元素变量名,与#{item}对应 -->
<!-- open:集合遍历时,需要拼接到遍历sql语句的前面 -->
<!-- close:集合遍历时,需要拼接到遍历sql语句的后面 -->
<!-- separator:集合遍历时,需要拼接到遍历sql语句之间的分隔符号 -->
<foreach collection="ids" item="id" open=" AND id IN ( " close=" ) " separator=",">#{id}</foreach>
</if>
</sql>
注意事项
如果parameterType不是POJO类型,而是List或者Array的话,那么foreach语句中,collection属性值需要固定写死为list或者array。
2.5 存在唯一约束时,不存在时插入,存在时更新批量更新
INSERT 语句的一部分,如果指定 ON DUPLICATE KEY UPDATE ,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则在出现重复值的行执行UPDATE,如果不会导致唯一值列重复的问题,则插入新行。
sql 语句原型:
insert into table (player_id,award_type,num) values(20001,0,1) on DUPLICATE key update num=num+values(num)
批量执行时,执行效率大幅度提高。
<insert id="batchUpdate" parameterType="java.util.List">
insert into t_a
(id,a1,a2,a3)
values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.id},
#{item.a1},
#{item.a2},
#{item.a3})
</foreach>
ON DUPLICATE KEY UPDATE
a1 = VALUES(a1),
a2 = VALUES(a2)
</insert>
columnList:需要更新的字段(检查对象中不为null的字段集合,例如:id,a1,a2,a3)
- 在对象中取值的字符串,与collection对应,例如:#{item.id}, #{item.a1}, #{item.a2}, #{item.a3}
- 修改更新的字段集合,例如:a1 =a1 + VALUES(a1), a2 = VALUES(a2), VALUES() 表示更新的字段