Mybatis的动态SQL实现

一、动态SQL简介
MyBatis的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。有些时候,SQL语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息。使用Oracle的序列、mySQL的函数生成Id。这时我们可以使用动态SQL。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
MyBatis中用于实现动态SQL的元素主要有:
1、if和where
2、choose(when,otherwise)
3、trim
4、set
5、foreach
下面将逐一进行介绍。

二、动态SQL的元素详解
首先来介绍一下SQL片段,它可以把动态SQL的判断部分独立处理,以便其他查询进行复用。
SQL片段定义方式:
[java] view plain copy
print ?
  1.        
  2.        定义sql片段  
  3. id是sql片段的唯一标识,便于下面语句的引用。通常把SQL片段设计成基于单表来定义sql片段,这样话这个sql片段可重用性才高。  
  4. 注意:在sql片段中不要包括 where  
  5.  –>  
  6. ”query_user_where”>  
  7.        
  8.         <if >  
  9.                   
  10.         if>  
  11.           
  12.   
  13.   
  14.           
  15.                    
  16.                          
  17.           
  18.   
        
    

            

            
            


            

                        

    

引用SQL片段
[java] view plain copy
print ?
  1.          
  2.       
  3.     ”query_user_where”>  
  4.       
  5.   
        
        
        
        
    


1、if和where

if就是简单的条件判断,利用if语句我们可以实现某些简单的条件选择。动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。
使用示例:
查询语句块:
[java] view plain copy
print ?
  1. “findUserList” parameterType=“com.kang.pojo.UserQueryVo”   
  2.             resultType=”com.kang.pojo.UserCustom”>  
  3.     SELECT * FROM USER  
  4.     
  5.     where可以自动去掉条件中的第一个and  
  6.      –>  
  7.          
  8.         ”query_user_where”>  
  9.         
  10.   


where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子的,MyBatis会智能的帮你处理。如果所有的条件都不满足那么MyBatis就会查出所有的记录;如果输出后是and这个单词开头的,MyBatis会把第一个单词and忽略,当然如果是or开头的,MyBatis也会把它忽略。此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。
SQL片段:
[java] view plain copy
print ?
  1. “query_user_where”>  
  2.                <if test=“userCustom!=null”>  
  3.             <if test=“userCustom.sex!=null and userCustom.sex!=””>  
  4.                 and user.sex = #{userCustom.sex}  
  5.             if>  
  6.             <if test=“userCustom.username!=null and userCustom.username!=””>  
  7.                 and user.username LIKE ’%${userCustom.username}%’  
  8.             if>  
  9.         if>  
  10.   

               
            
                and user.sex = #{userCustom.sex}
            
            
                and user.username LIKE '%${userCustom.username}%'
            
        
上述配置意思非常简单,如果你提供了sex参数,那么就要满足sex!=null和sex!=”两个条件,同样如果你提供了username参数的时候,也需要满足相应的条件,之后就是返回满足这些条件的所有user,这是非常有用的一个功能,以往我们使用其他类型框架或者直接使用JDBC的时候, 如果我们要达到同样的选择效果的时候,我们就需要拼SQL语句,这是极其麻烦的,比起来,上述的动态SQL就要简单多了。
如果输入是sex=1和username=null,那么上述配置产生的SQL语句就是:
SELECT * FROM USER where user.sex = #{userCustom.sex}
而不是:
SELECT * FROM USER and user.sex = #{userCustom.sex}
因为where标签自动加入了”where”这个关键字,而且去掉了”and”这个单词,并在where的前后自动加入了空格,最终组合成相应的SQL语句。

2、choose
choose元素的作用就相当于JAVA中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。
使用示例:
[java] view plain copy
print ?
  1. “findUserList” parameterType=“com.kang.pojo.UserQueryVo”   
  2.             resultType=”com.kang.pojo.UserCustom”>  
  3.     SELECT * FROM USER  
  4.     
  5.     ”userCustom.sex!=null and userCustom.sex!=””>  
  6.       and user.sex = #{userCustom.sex}  
  7.       
  8.     ”userCustom.username!=null and userCustom.username!=””>  
  9.      and user.username LIKE ’%${userCustom.username}%’  
  10.       
  11.       
  12.       and user.id = 1  
  13.       
  14.     
  15.   

上述配置中,when元素表示当when中的条件满足的时候就输出其中的内容,跟JAVA中的switch效果差不多的是按照条件的顺序,当when中有条件满足的时候,就会跳出choose,即所有的when和otherwise条件中,只有一个会输出,当所有的条件都不满足的时候就输出otherwise中的内容。

3、trim
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能。
使用示例:
[java] view plain copy
print ?
  1. “findUserList” parameterType=“com.kang.pojo.UserQueryVo”   
  2.             resultType=”com.kang.pojo.UserCustom”>  
  3.     SELECT * FROM USER  
  4.     ”where” prefixOverrides=“and |or”>    
  5.        <if test=“userCustom!=null”>  
  6.      <if test=“userCustom.sex!=null and userCustom.sex!=””>  
  7.                 and user.sex = #{userCustom.sex}  
  8.      if>  
  9.      <if test=“userCustom.username!=null and userCustom.username!=””>  
  10.                 and user.username LIKE ’%${userCustom.username}%’  
  11.      if>  
  12.        if>  
  13.         
  14.     
  

4、set
set元素主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的,主要是在set标签包含的语句前输出一个set。如果包含的语句是以逗号结束的话将会把该逗号忽略。如果set包含的内容为空的话则会出错。有了set元素我们就可以动态的更新那些修改了的字段,而不用每次更新全部字段。
使用示例:
[java] view plain copy
print ?
  1. “updateUser” parameterType=“com.kang.pojo.User”>  
  2.     update user  
  3.         
  4.         <if test=“username != null”>    
  5.             username=#{username},  
  6.         if>    
  7.         <if test=“birthday != null”>    
  8.             birthday=#{birthday},    
  9.         if>    
  10.         <if test=“sex != null”>    
  11.             sex=#{sex},    
  12.         if>    
  13.         <if test=“address != null”>    
  14.            address=#{address}  
  15.         if>    
  16.         
  17.     where id = #{id}    
  18.     

    update user
      
          
            username=#{username},
          
          
            birthday=#{birthday},  
          
          
            sex=#{sex},  
          
          
           address=#{address}
          
      
    where id = #{id}  
  

5、foreach
foreach的主要用在构建in条件中,它可以在SQL语句中迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束。
collection属性用于指定传入参数的类型。该属性是必须指定的,在不同情况下,该属性的值是不一样的,主要有一下3种情况:
如果传入的是单参数且参数类型是一个List类型的时候,collection属性值为list。
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map。实际上在传入参数的时候,MyBatis也是把它封装成一个Map的,List实例将会以“list”作为键,而数组实例将会以“array”作为键。这个时候collection属性值就是传入的List或array对象在封装自身的map里面中的对应key。

传入List的使用示例:

首先是查询接口:
public List findUserList(List ids);  
对应xml文件中的配置:
[java] view plain copy
print ?
  1. “findUserList” resultType=“com.kang.pojo.UserCustom”>    
  2.     SELECT * FROM USER WHERE id IN    
  3.     ”list” index=“index” item=“item” open=“(“ separator=“,” close=“)”>    
  4.         #{ids}    
  5.         
  6.     
  
可以看到,foreach标签描述中的参数和接口中的输入参数保持一致。
具体代码使用:
[java] view plain copy
print ?
  1. //前述代码略  
  2. UserMapper userMapper = session.getMapper(UserMapper.class);    
  3. List ids = new ArrayList();    
  4. ids.add(1);    
  5. ids.add(3);    
  6. ids.add(6);    
  7. List users = userMapper.findUserList(ids);    
  8. for (User user : users)    
  9.         System.out.println(user);    
  10. session.close();    
//前述代码略
UserMapper userMapper = session.getMapper(UserMapper.class);  
List ids = new ArrayList();  
ids.add(1);  
ids.add(3);  
ids.add(6);  
List users = userMapper.findUserList(ids);  
for (User user : users)  
        System.out.println(user);  
session.close();  

传入array数组的使用示例:
接口定义:
public List findUserList(int[] ids);  
对应xml文件中的配置:
[java] view plain copy
print ?
  1. “findUserList” resultType=“com.kang.pojo.UserCustom”>    
  2.     SELECT * FROM USER WHERE id IN    
  3.     ”array” index=“index” item=“item” open=“(“ separator=“,” close=“)”>    
  4.         #{ids}    
  5.         
  6.     
  

具体代码使用:
//前述代码略
[java] view plain copy
print ?
  1. UserMapper userMapper = session.getMapper(UserMapper.class);    
  2. int[] ids = {1,3,6,9};    
  3. List users = userMapper.findUserList(ids);    
  4. for (User user : users)    
  5.         System.out.println(user);    
  6. session.close();    
UserMapper userMapper = session.getMapper(UserMapper.class);  
int[] ids = {1,3,6,9};  
List users = userMapper.findUserList(ids);  
for (User user : users)  
        System.out.println(user);  
session.close();  
传入array数组的使用示例:
接口定义:
public List findUserList(Map params);  
对应xml文件中的配置:
[java] view plain copy
print ?
  1. “findUserList” resultType=“com.kang.pojo.UserCustom”>    
  2.     SELECT * FROM USER WHERE id IN    
  3.     ”ids” index=“index” item=“item” open=“(“ separator=“,” close=“)”>    
  4.         #{params}    
  5.         
  6.     
  

具体代码使用:
[java] view plain copy
print ?
  1. //前述代码略  
  2. UserMapper userMapper = session.getMapper(UserMapper.class);    
  3. final List ids = new ArrayList();    
  4.     ids.add(1);    
  5.     ids.add(2);    
  6.     ids.add(3);    
  7.     ids.add(6);    
  8.     ids.add(7);    
  9.     ids.add(9);    
  10.     Map params = new HashMap();    
  11.     params.put(”ids”, ids);   
  12. List users = userMapper.findUserList(ids);    
  13. for (User user : users)    
  14.         System.out.println(user);    
  15. session.close();   
//前述代码略
UserMapper userMapper = session.getMapper(UserMapper.class);  
final List ids = new ArrayList();  
    ids.add(1);  
    ids.add(2);  
    ids.add(3);  
    ids.add(6);  
    ids.add(7);  
    ids.add(9);  
    Map params = new HashMap();  
    params.put("ids", ids); 
List users = userMapper.findUserList(ids);  
for (User user : users)  
        System.out.println(user);  
session.close(); 


                
        
    

你可能感兴趣的:(mysql,mybatis,sql,框架,经验)