动态 SQL
动态 SQL 是 MyBatis 的强?特性之?。如果你使?过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接
SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后?个列名的逗号。利?动态 SQL,可以彻底摆脱这种痛苦。
使?动态 SQL 并??件易事,但借助可?于任何 SQL 映射语句中的强?的动态 SQL 语?,MyBatis 显著地提升了这?特性的易?性。
如果你之前?过 JSTL 或任何基于类 XML 语?的?本处理器,你对动态 SQL 元素可能会感觉似曾相识。在
MyBatis 之前的版本中,需要花时间了解?量的元素。借助功能强?的基于 OGNL 的表达式,MyBatis 3 替换了之前的?部分元素,??精简了元素种类,现在要学习的元素种类?原来的?半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
2.1 动态 SQL 之if标签
我们根据实体类的不同取值,使?不同的 SQL 语句来进?查询。?如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加??户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
2.1.1 持久层 Dao 接?
List<User> findByUser(User user);
2.1.2 持久层 Dao 映射配置
<select id="findByUser" resultType="com.soft.domain.User"
parameterType="com.soft.domain.User">
select * from user where 1=1
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null and username != ''">
and address like #{address}
</if>
</select>
注意:<if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使? OGNL 表达式的写法。
另外要注意 where 1=1 的作?~!
2.1.3****测试的代码
@Test
public void testFindByUser() {
User u = new User();
u.setUsername("%王%");
u.setAddress("%北京%");
List<User> users = userDao.findByUser(u);
for(User user : users) {
System.out.println(user);
} }
2.2 动态 SQL 之****标签
为了简化上? where 1=1 的条件拼装,我们可以采?标签来简化开发。
2.2.1 持久层 Dao 映射配置
<select id="findByUser" resultType="com.soft.domain.User"
parameterType="com.soft.domain.User">
select * from user
<where>
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null and username != ''">
and address like #{address}
</if>
</where>
</select>
where****的好处可以?动过滤第?个and关键字,不要再写sql语句不?再写where
2.3 动态标签之<foreach标签
2.3.1 需求
传?多个 id 查询?户信息,?下边两个 sql 实现:
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)
这样我们在进?范围查询时,就要将?个集合中的值,作为参数动态添加进来。
这样我们将如何进?参数的传递?
2.3.1.1 在 QueryVo 中加??个 List 集合?于封装参数
public class QueryVo {
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
2.3.2 持久层 Dao 接?
List<User> findUserInIds(QueryVo vo);
2.3.3 持久层 Dao 映射配置
<select id="findUserInIds" resultType="com.soft.domain.User"
parameterType="com.soft.domain.QueryVo">
-- select * from user where id in(50,51,53,54);
select * from USER
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" item="uid" separator="," open="id in("
close=")">
\#{uid}
</foreach>
</if>
</where>
</select>
<foreach>标签?于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,?成的变量名
sperator:代表分隔符
2.3.3.1 编写测试?法
@Test
public void testFindUserInIds(){
QueryVo queryVo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(50);
ids.add(51);
ids.add(53);
ids.add(54);
queryVo.setIds(ids);
List<User> userInIds = userDao.findUserInIds(queryVo);
for (User userInId : userInIds) {
System.out.println(userInId);
}
}
2.4 Mybatis 中简化编写的 SQL ?段
Sql 中可将重复的 sql 提取出来,使?时? include 引?即可,最终达到 sql 重?的?的。
2.4.1 定义代码?段
select * from user
<sql id="userSQL">
select * from user
</sql>
引?代码?段*
<select id="findByUser" resultType="com.soft.domain.User"
parameterType="com.soft.domain.User">
-- select * from user
<include refid="userSQL"></include>
<where>
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null and username != ''">
and address like #{address}
</if>
</where>
</select>
|