动态SQL中的元素
元素 | 说明 |
<if> | 判断语句,用于单条件分支判断 |
<choose>、(<when>、<otherwise>) | 相当于java中的switch...case...default语句,用于多条件分支判断 |
<where>、<trim>、<set> | 处理SQL拼装,特殊字符问题 |
<foreach> | 循环语句,常用于in语句等列举条件中 |
<bind> | 从OGNL表达式中创建一个变量,并将其绑定到上下文,常用于模糊查询的sql中 |
1.<if>元素
在使用<if>元素时,只要test属性中的表达式为true,就会执行元素中的条件语句
(1)CustomerMapper.xml
<mapper namespace="com.itcast.mapper.CustomerMapper">
<!--<if>元素使用-->
<select id="findCustomerByNameAndJobs"
parameterType="com.itcast.po.Customer"
resultType="com.itcast.po.Customer"
select * from t_customer where 1=1
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs" !=null and jobs !=''">
and jobs=#{jobs}
</if>
</select>
</mapper>
使用<if>元素的test属性分别对username和jobs进行了非空判断(test属性多用于条件判断语句中,用于判断真假,大部分的场景中都是进行非空判断,有时候也需要判断字符串,数字和枚举等),如果传入的查询条件非空就进行动态SQL组装
(2)测试类MyBatisTest
/*
根据客户姓名和职业组合条件查询客户信息列表
*/
@Test
public void findCustomerByNameAndJobsTest(){
//通过工具类生成sqlsession对象
SqlSession sqlSession =MyBatisUtils.getSession();
//创建Customer对象,封装需要组合查询的条件
Customer customer=new Customer();
customer.setUsername("jack");
customer.setJobs("teacher");
//执行sqlSession 的查询方法,返回结果集
List<Customer> customers=sqlSession.selectList("com.itcast.mapper"+".CustomerMapper.findCustomerByNameAndJobs",customer);
//输出查询结果信息
for(Customer customer2:customers){
//打印输出结果
System.out.println(customer2);
}
//关闭sqlSession
sqlSession.close();
}
}
2.<choose>、<when>、<otherwise>元素
当客户名称不为空,则只根据客户名称进行客户筛选
当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选
当客户名称和客户职业都为空,则要求查询出所有电话不为空的客户信息
案例:
(1)在映射文件CustomerMapper.xml中
<!--<choose>(<when>、<otherwise>)元素使用-->
<select id="findCustomerByNameOrJobs"
parameterType="com.itcast.po.Customer"
resultType="com.itcast.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs=#{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
在上述代码中,使用了<choose>元素进行SQL拼装,当第一个<when>元素中的条件为真,则只动态组装第一个<when>元素内的SQL片段,否则就继续向下判断第二个<when>元素中的条件是否为真,以此类推.当前面所有<when>元素中的条件都不为真时,则只组装<otherwise>元素内的SQL片段
(2)测试
/*
根据客户姓名或职业查询客户信息列表
*/
@Test
public void findCustomerByNameOrJobsTest(){
//通过工具类生成sqlsession对象
SqlSession sqlSession =MyBatisUtils.getSession();
//创建Customer对象,封装需要组合查询的条件
Customer customer=new Customer();
customer.setUsername("jack");
customer.setJobs("teacher");
//执行sqlSession 的查询方法,返回结果集
List<Customer> customers=sqlSession .selectList("com.itcast.mapper"+".CustomerMapper.findCustomerByNameOrJobs",customer);
//输出查询结果信息
for(Customer customer2:customers){
//打印输出结果
System.out.println(customer2);
}
//关闭sqlSession
sqlSession.close();
}
3.<where>、<trim>元素
select * from t_customer where and username like concat('%',?,'%')
<!--<where>元素-->
<select id="findCustomerByNameAndJobs"
parameterType="com.itcast.po.Customer"
resultType="com.itcast.po.Customer"
select * from t_customer
<where>
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs" !=null and jobs !=''">
and jobs=#{jobs}
</if>
</where>
</select>
<where>元素会自动判断组合条件下拼装的SQL语句,只有<where>元素内的条件成立时,才会在拼接SQL中加入where关键字,否则将不会添加;即使where之后的内容有多余的"AND"或"OR",<where>元素也会自动将它们去除.
上述代码还可以修改成如下形式:
<!--<trim>元素-->
<select id="findCustomerByNameAndJobs"
parameterType="com.itcast.po.Customer"
resultType="com.itcast.po.Customer">
select * from t_customer
<trim prefix="where" prefixOverrides="and">
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs" !=null and jobs !=''">
and jobs=#{jobs}
</if>
</trim>
</select>
<trim>元素的作用就是去除一些特殊的字符串,它的prefix属性代表的是语句的前缀(这里使用where来连接后面的SQL片段),而prefixOverrides属性代表的是需要去除的那些特殊字符串(这里定义了要去除SQL中的and)
4.<set>元素
<set>元素主要用于更新操作,主要作用是在动态包含的SQL语句前输出一个SET关键字,并将SQL语句中最后一个多余的逗号去除
案例:使用<set>元素对映射文件中更新客户信息的SQL语句进行修改
<!--<set>元素-->
<update id="updateCustomer"
parameterType="com.itcast.po.Customer">
update t_customer
<set>
<if test="username !=null and username !=''">
username =#{username},
</if>
<if test="jobs" !=null and jobs !=''">
jobs=#{jobs},
</if>
<if test="phone !=null and phone !=''">
phone=#{phone},
</if>
</set>
where id=#{id}
</update>
上述代码中,使用了<set>和<if>元素相结合的方式来组装update语句.其中<set>元素会动态前置SET关键字,同时也会消除SQL语句中最后一个多余的逗号;<if>元素用于判断相应的字段是否传入值,如果传入的更新字段非空,就将此字段进行动态SQL组装,并更新此字段,否则此字段不执行更新.
5.<foreach>元素
<foreach>元素通常在构建IN条件语句时使用
<select id="findCustomerByIds" parameterType="List"
resultType="com.itcast.po.Customer">
select * from t_customer where id in
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
属性名 | 说明 |
item | 循环中当前的元素 |
index | 当前元素在集合的位置下标 |
collection | 配置的list是传递过来的参数类型(首字母小写),它可以是一个list,array,或者collection,Map集合的键,POJO包装类中数组或集合类型的属性名等 |
open/close | 配置的是以什么符号将这些集合元素包装起来 |
separator | 配置分隔符 |
6.<bind>元素
<bind>元素可以通过OGNL表达式来创建一个上下文变量,使用方式如下:
<!--根据客户名模糊查询客户信息-->
<select id="findCustomerByName" parameterType="com.itcast.po.Customer"
resultType="com.itcast.po.Customer">
<!--_parameter.getUsername()也可直接写成传入的字段属性名,即username-->
<bind name="pattern_username"
value="'%'+_parameter.getUsername()+'%'"/>
select * from t_customer
where
username like #{pattern_username}
</select>
测试代码:
/*
<bind>元素的使用,根据客户姓名模糊查询客户信息
*/
@Test
public void findCustomerByNameTest(){
//通过工具类生成sqlsession对象
SqlSession sqlSession =MyBatisUtils.getSession();
//创建Customer对象,封装需要组合查询的条件
Customer customer=new Customer();
customer.setUsername("j");
//执行sqlSession 的查询方法,返回结果集
List<Customer> customers=sqlSession .selectList("com.itcast.mapper"+".CustomerMapper.findCustomerByName",customer);
//输出查询结果信息
for(Customer customer2:customers){
//打印输出结果
System.out.println(customer2);
}
//关闭sqlSession
sqlSession.close();
}