复杂查询 — 动态SQL
多条件查询
普通的sql查询多条判断条件时
select * from emp
where 1=1 and ename = ? and job = ? and sal = ?
当其中一个条件为空时或者未提供会报错
mybatis提供了 if 标签
<if test="name != null">
and ename like concat("%",#{name},"%")
</if>
判断失败则不加入sql语句
实例
//map传参
List<Emp> selectByCondition1(Map<String,Object> searchMap);
//顺序传参
List<Emp> selectByCondition2(String ename,String job,Double sal);
//对象传参
List<Emp> selectByCondition3(SearchMap searchMap);
public class SearchMap {
private String name;
private String job;
private Double sal;
}
<select id="selectByCondition3" parameterType="hasmap" resultMap="empMap">
select * from emp where
<if test="ename != null">
ename like concat("%",#{ename},"%")
</if>
<if test="job != null">
and job = #{job}
</if>
<if test="sal != null">
and sal > #{sal}
</if>
</select>
<select id="selectByCondition3" resultMap="empMap">
select * from emp where
<if test="param1 != null">
ename like concat("%",#{param1},"%")
</if>
<if test="param2 != null">
and job = #{param2}
</if>
<if test="param3 != null">
and sal > #{param3}
</if>
</select>
<select id="selectByCondition3" parameterType="org.lanqiao.pojo.SearchMap" resultMap="empMap">
select * from emp where
<if test="name != null">
ename like concat("%",#{name},"%")
</if>
<if test="job != null">
and job = #{job}
</if>
<if test="sal != null">
and sal > #{sal}
</if>
</select>
这样还是存在问题 如果其中第一条判断失败 那么第二条加入 会变成
select * from emp where and job = #{job}多余的and导致出错
可以通过一般方式解决
select * from emp where 1=1
<if test="name != null">
and ename like concat("%",#{name},"%")
</if>
<if test="job != null">
and job = #{job}
</if>
<if test="sal != null">
and sal > #{sal}
</if>
为了解决这个问题 mybatis提供了 where标签
select * from emp
<where>
<if test="name != null">
and ename like concat("%",#{name},"%")
</if>
<if test="job != null">
and job = #{job}
</if>
<if test="sal != null">
and sal > #{sal}
</if>
</where>
where标签会自动出掉多余的第一个and或者or
foreach查询
需求
传入多个 id 查询用户信息,用下边两个 sql 实现:
扫描二维码关注公众号,回复:
9543856 查看本文章
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。
这样我们将如何进行参数的传递?
在 QueryVo 中加入一个 List 集合用于封装参数
/**
* <p>Description: 查询的条件</p>
*/
public class QueryVo implements Serializable {
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
持久层 Dao 接口
/**
* 根据 id 集合查询用户
* @param vo
* @return
*/
List<User> findInIds(QueryVo vo);
持久层 Dao 映射配置
<!-- 查询所有用户在 id 的集合之中 -->
<select id="findInIds" resultType="user" parameterType="queryvo">
<!-- select * from user where id in (1,2,3,4,5); -->
<include refid="defaultSql"></include>
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
SQL 语句:
select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:
-
collection:代表要遍历的集合元素,注意编写时不要写#{}
-
open:代表语句的开始部分
-
close:代表结束部分
-
item:代表遍历集合的每个元素,生成的变量名
-
sperator:代表分隔符
1.3.3.1.编写测试方法
@Test
public void testFindInIds() {
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(41);
ids.add(42);
ids.add(43);
ids.add(46);
ids.add(57);
vo.setIds(ids);
//6.执行操作
List<User> users = userDao.findInIds(vo);
for(User user : users) {
System.out.println(user);
}
}
Mybatis 中简化编写的 SQL 片段 sql冗余
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。
1 定义代码片段
<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
select * from user
</sql>
2 引用代码片段
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
<include refid="defaultSql"></include>
</select>
<!-- 根据 id 查询 -->
<select id="findById" resultType="UsEr" parameterType="int">
<include refid="defaultSql"></include>
where id = #{uid}
</select>