在 MyBatis 的 SQL映射文件中,有时候需要根据一些查询条件,来选择不同的SQL语句,如果每一个场景都重写SQL,很显然效率没有很高,而 MyBatis 的动态SQL很好的解决了这种问题,根据条件动态的处理 SQL, 特别简单的说就是,写一次SQL,但是根据分支等的跳转,在多个场景下也可以使用,例如:
- 当查询条件由于参数不同而无法确定具体是什么,可以使用
<where>
标签包含 - 在
<where>
可以使用<if test="....">
分条件进行处理,实现动态 <foreach>
遍历标签放到后面代码中具体说
在此之外,动态SQL同时结局了,在原生 JDBC 中需要拼接SQL语句时由于书写问题,而导致报错
1. where 和 if 标签
1.1 UserMapper 接口
/**
* 根据条件查询
* @return
*/
List<User> findUserByCondition(User user);
1.2 UserMapper.xml
<select id="findUserByCondition" resultType="cn.ideal.domain.User" parameterType="cn.ideal.domain.User">
select * from user
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="gender != null">
and gender = #{gender}
</if>
</where>
</select>
注意:在SQL中,“and” 用来拼接已有一个或多个查询条件的语句,当此语句为第一个查询条件的时候,会因为 <where>
的存在屏蔽第一个 “and”
1.3 MyBatisTest
/**
* 根据条件查询
* @throws Exception
*/
@Test
public void testFindByCondition() throws Exception{
User user = new User();
user.setUsername("汤姆");
user.setGender("女");
List<User> users = userMapper.findUserByCondition(user);
for (User u : users){
System.out.println(u);
}
1.4 执行效果
1.5 复用SQL
有一些语句,在我们的程序中,使用的频率特别高,这个时候,我们也可以对其进行,单独的配置,然后达到复用的效果
首先,我们需要对其进行简单的声明
<sql id="xxxxx">
<!-- 复用的SQL -->
</sql>
在需要引用的地方,我们可以这样引用
<where>
include refid="xxxxx"></include>
<!-- 可能还用引用别的 -->
</where>
2. foreach标签
提出这样一种需求,在用户中查询寻多个id,例如(12,16,17)我们可以这样写SQL
select * from user where id=12 or id=16 or id=17
或者这样
select * from user where id in (12,16,17)
而这种情况下,我们需要向SQL中传递一个数据或者List类型的参数,然后使用 <foreach>
标签去遍历然后解析
2.1 UserMapper 接口
/**
* 根据QueryUserVo中提供的id集合,查询用户信息
* @param vo
* @return
*/
List<User> findUserInIds(QueryUserVo vo);
2.2 UserMapper.xml
<select id="findUserInIds" resultType="cn.ideal.domain.UserInstance" parameterType="cn.ideal.domain.QueryUserVo">
select * from user
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
解释一下
- collection 指定输入对象中的集合属性
- item 为每次遍历生成的对象名
- open为开始遍历时拼接的字符串
- close为结束便利时要拼接的字符串
- separator为遍历两个对象中间需要拼接的串
本例中,我哦们使用了 select * from user where id in (12,16,17)
这种形式,如果想使用 or那种形式,只需要修改拼接格式就可以了
/**
* 根据QueryUserVo中提供的id集合,查询用户信息
* @throws Exception
*/
@Test
public void testfindUserInIds() throws Exception{
QueryUserVo vo = new QueryUserVo();
List<Integer> list = new ArrayList<Integer>();
list.add(12);
list.add(16);
list.add(17);
vo.setIds(list);
List<User> users = userMapper.findUserInIds(vo);
for (User u : users){
System.out.println(u);
}
}