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中的特殊字符,需要通过实体转义来实现 < 对应 < > 对应 > --> <select id="selectByChoose" parameterType="map" resultType="Emp"> select <include refid="Base_Column_List"></include> from emp <choose> <when test="sal > 2500"> where sal>#{sal} </when> <otherwise> where sal<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>
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 }
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概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取
mybatis动态sql之利用sql标签抽取可重用的sql片段
MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段