MyBatis动态SQL

Posted 57容杰龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis动态SQL相关的知识,希望对你有一定的参考价值。

1.动态SQL解决拼接复杂的的SQL语句

  •    MyBatis的动态SQL是基于OGNL表达式的
  •   OGNL(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言
  •   if, choose, when, otherwise, trim, where, set, foreach标签

2.if标签

    <!-- 按empno查询员工记录,如果empno为空,默认查询出所有员工信息
     if标签: 如果test表达式的值不成立  则不会添加标签内的sql内容    表达式支持OGNL的语法
     parameterType="integer"  
     test="empno!=null"
     There is no getter for property named \'empno\' in \'class java.lang.Integer\'
     OGNL表达式的规则会根据empno从当前的传入的参数对象中去寻找名叫empno的属性,而integer
     里面没有该属性,所以会报找不到属性
     解决方案:
     1.将当前的程序或者当前的模块中的需要查询的条件数据封装成条件对象
     2.使用原对象传值
     3.做成map  key:value   OGNL语法可以根据empno 从 key中查找
      -->
     <select id="selectByPrimaryKey" parameterType="map" resultType="Emp">
         select 
         <include refid="Base_Column_List"></include>
         from emp
         <if test="empno!=null">
             where empno=#{empno}
         </if>
     </select>
1 @MyBatisAnnotation
2 public interface EmpMapper {
3 
4     Emp selectByPrimaryKey(Map<String,Object> params);//按id查询
 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration(locations="classpath:spring-ssm.xml")
 3 public class TestSSM {
 4     Map<String,Object> map;
 5     @Resource
 6     EmpMapper empMapper;
 7     
 8     @Test
 9     public void testFindByIf(){
10         map=new HashMap<>();
11         //map.put("empno", null);为空则查询所有
12         map.put("empno", 7788);
13         //map.put("empno", 10086);不存在则返回null
14         Emp emp = empMapper.selectByPrimaryKey(map);
15         System.out.println(emp);
16     }

3.choose标签

     <!-- 
         
         小于、大于符号属于xml中的特殊字符,需要通过实体转义来实现
         <     对应    &lt;
         >     对应    &gt;  
      -->
      <select id="selectByChoose" parameterType="map" resultType="Emp">
          select 
          <include refid="Base_Column_List"></include>
          from emp
          <choose>
              <when test="sal &gt; 2500">
                  where sal&gt;#{sal}
              </when>
              <otherwise>
                  where sal&lt;2500
              </otherwise>
          </choose>
      </select>
   List<Emp> selectByChoose(Map<String,Object> map);
1     @Test
2     public void testSelectByChoose(){
3         map=new HashMap<>();
4         map.put("sal", 1000);
5         List<Emp> list = empMapper.selectByChoose(map);
6         for (Emp emp : list) {
7             System.out.println(emp);
8         }
9     }

4.where标签

<!-- 
         按照ename、job、deptno动态传参实现查询语句
      -->
     <select id="selectByWhere" parameterType="map" resultType="Emp">
         select 
         <include refid="Base_Column_List"></include>
         from emp
         <!-- 替代原有的sql关键字where 会动态拼接里面的sql到上面sql语句上  并且自动去除多余的and或or  
         也可以自动处理空格 -->
         <where>
             <if test="ename!=null">
                 and ename=#{ename}
             </if>
             <if test="job!=null">
                 and job=#{job}
             </if>
             <if test="deptno!=null">
                 and deptno=#{deptno}
             </if>
         </where>
     </select>
 List<Emp> selectByWhere(Map<String,Object> map);
 1     @Test
 2     public void testSelectByWhere(){
 3         map=new HashMap<>();
 4 //        map.put("ename", "SMITH");
 5         map.put("job", "CLERK");
 6         map.put("deptno", 20);
 7         
 8         List<Emp> list = empMapper.selectByWhere(map);
 9         for (Emp emp : list) {
10             System.out.println(emp);
11         }
12     }

 

<if test="name!= null">  

            and name like "%"#{name}"%"  

        </if> 

5.set标签

如果set包含的内容为空的话则会出错

<!-- set
         动态更新 Emp  可以通过一条sql语句解决所有的关于Emp单表中的更新情况
      -->
      <update id="updateBySet" parameterType="Emp">
          update emp
          <set><!-- 替代set关键字   动态删除语句后面多余的逗号,并且可以处理空格 -->

              <if test="ename!=null">ename=#{ename},</if>
              <if test="job!=null">job=#{job},</if>
              <if test="mgr!=null">mgr=#{mgr},</if>
              <if test="hiredate!=null">hiredate=#{hiredate},</if>
              <if test="sal!=null">sal=#{sal},</if>
              <if test="comm!=null">comm=#{comm},</if>
              <if test="deptno!=null">deptno=#{deptno},</if>
          
          </set>
          <if test="empno!=null">
              where empno=#{empno}
          </if>
      </update>
int updateBySet(Emp emp);
1     @Test
2     public void testUpdateBySet(){
3         Emp emp=new Emp();
4         emp.setEmpno(7934);
5         emp.setSal(3000.0);
6         int num = empMapper.updateBySet(emp);
7         System.out.println(num);
8     }

6.trim标签

      <!-- trim  可以动态给包括的语句块去除两端的内容   也可以添加两端的内容
          prefix:在前面添加内容  
          suffix:在后面添加内容
          prefixOverrides:忽略前面多余的内容
          suffixOverrides:忽略后面多余的内容
       -->
      <update id="updateByTrim" parameterType="Emp">
          update emp  
          <trim prefix="set" suffix="where" prefixOverrides="," suffixOverrides=",">
              <if test="ename!=null">,ename=#{ename},</if>
              <if test="job!=null">job=#{job},</if>
              <if test="mgr!=null">mgr=#{mgr},</if>
              <if test="hiredate!=null">hiredate=#{hiredate},</if>
              <if test="sal!=null">sal=#{sal},</if>
              <if test="comm!=null">comm=#{comm},</if>
              <if test="deptno!=null">deptno=#{deptno},</if>
          </trim>
          empno=#{empno}
      </update>
int updateByTrim(Emp emp);
1 @Test
2     public void testUpdateByTrim(){
3         Emp emp=new Emp();
4         emp.setEmpno(7934);
5         emp.setSal(2000.0);
6         int num = empMapper.updateByTrim(emp);
7         System.out.println(num);
8     }
     <!-- 动态插入,如果Emp的某个字段有值,则插入数据到数据库,如果没有值,则不插入该字段,使用默认值 -->
      
      <insert id="insertByTrim" parameterType="Emp">
          insert into emp
          <trim prefix="(" suffix=")" suffixOverrides=",">
              <if test="empno!=null">empno,</if>
              <if test="ename!=null">ename,</if>
              <if test="job!=null">job,</if>
              <if test="mgr!=null">mgr,</if>
              <if test="hiredate!=null">hiredate,</if>
              <if test="sal!=null">sal,</if>
              <if test="comm!=null">comm,</if>
              <if test="deptno!=null">deptno,</if>
          </trim>
          values
          <trim prefix="(" suffix=")" suffixOverrides=",">
              <if test="empno!=null">#{empno},</if>
              <if test="ename!=null">#{ename},</if>
              <if test="job!=null">#{job},</if>
              <if test="mgr!=null">#{mgr},</if>
              <if test="hiredate!=null">#{hiredate},</if>
              <if test="sal!=null">#{sal},</if>
              <if test="comm!=null">#{comm},</if>
              <if test="deptno!=null">#{deptno},</if>
          </trim>
      </insert>
View Code
int insertByTrim(Emp emp);
1     @Test
2     public void testInsertByTrim(){
3         Emp emp=new Emp();
4         emp.setEmpno(8000);
5         emp.setSal(2000.0);
6         emp.setComm(1000d);
7         int num = empMapper.insertByTrim(emp);
8         System.out.println(num);
9     }
View Code

7.foreach标签

      <!-- foreach 实现批量删除 
      collection  设置需要循环的集合      用于设置传入的参数类型或者是参数对应的key值  
      传入List类型的时候    填list
      传入Array的时候        填array
      传入map类型的时候      填的是需要传入的集合数据,在map中对应的key(empnos)   [key:value] ["empnos":{},"ename":"xxx"]
      item          设置每次循环的变量名,类似jstl的  var  
      index       设置代表第几次循环的变量 
      open        设置循环开始位置添加的内容
      separator   设置每次循环过程中的分割符号
      close       设置循环结束位置添加的内容
      
      根据传入的empno实现批量删除
      
      1.传入list
       -->
       <delete id="deleteForeach" parameterType="list" >
           delete from emp where empno in
           <foreach collection="list" item="empno"  index="index"  open="(" separator="," close=")">
               #{empno}
           </foreach>
       </delete>
 int deleteForeach(List<Integer> list);
    @Test
    public void deleteForeach(){
        List<Integer> list=new ArrayList<>();
        list.add(8000);
        list.add(9000);
        int num = empMapper.deleteForeach(list);
        System.out.println(num);
    }
1        <!-- 2.传入map的参数 -->
2        
3        <delete id="deleteForeach2" parameterType="map">
4            delete from emp where empno in
5            <foreach collection="empnos" item="empno" open="(" separator="," close=")">
6                #{empno}
7            </foreach>
8        </delete>
    int deleteForeach2(Map<String,Object> map);
 1     @Test
 2     public void deleteForeach2(){
 3         map=new HashMap();
 4         ArrayList<Integer> list = new ArrayList<Integer>();
 5         list.add(8000);
 6         list.add(9000);
 7         map.put("empnos", list);
 8         int num = empMapper.deleteForeach2(map);
 9         System.out.println(num);
10     }

 

以上是关于MyBatis动态SQL的主要内容,如果未能解决你的问题,请参考以下文章

mybatis动态sql片段与分页,排序,传参的使用

Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取

mybatis动态sql之利用sql标签抽取可重用的sql片段

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

[mybatis]动态sql_sql_抽取可重用的sql片段

Mybatis动态sql