作用

  • 可以定义代码片段
  • 可以进行逻辑判断
  • 可以进行循环处理(批量处理),使条件判断更为简单

使用方式

  • 通过mybatis中与动态sql有关的标签来实现

< sql >标签 + < include >标签

作用

  • < sql >标签:可以用来定义代码片段
  • < include >标签:对定义的代码片段进行引用

用法

UsersMapper.xml映射文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.mapper.UsersMapper">
  4. <!--
  5. 自定义代码片段
  6. -->
  7. <sql id="allColumns">
  8. id, username, birthday, sex, address
  9. </sql>
  10. <!--
  11. //获取全部用户信息
  12. List<Users> getAll();
  13. -->
  14. <select id="getAll" resultType="user">
  15. select
  16. <include refid="allColumns"/>
  17. from
  18. users
  19. </select>
  20. </mapper>

< if > 标签 + < where >标签

作用

  • < if >标签:进行条件判断
  • < where >标签:进行多条件拼接,在查询,删除,更新中使用

用法

UsersMapper.java接口代码

  1. package com.example.mapper;
  2. import com.example.pojo.User;
  3. import java.util.List;
  4. /**
  5. * 数据访问层的接口,定义对数据库完成的CRUD的操作
  6. */
  7. public interface UsersMapper {
  8. //根据给定的查询条件进行多条件查询
  9. List<User> selectOnCondition(User user);
  10. }

UsersMapper.xml映射文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.mapper.UsersMapper">
  4. <!--
  5. //根据给定的查询条件进行多条件查询
  6. List<User> selectOnCondition(User user);
  7. private Integer id;
  8. private String userName;
  9. private Date birthday;
  10. private String sex;
  11. private String address;
  12. -->
  13. <select id="selectOnCondition" parameterType="user" resultType="user">
  14. select
  15. <include refid="allColumns"/>
  16. from
  17. users
  18. <where>
  19. <if test="userName != null and userName != ''">
  20. and username like concat('%', #{userName},'%')
  21. </if>
  22. <if test="birthday != null">
  23. and birthday=#{birthday}
  24. </if>
  25. <if test="sex != null and sex != ''">
  26. and sex=#{sex}
  27. </if>
  28. <if test="address != null and address != ''">
  29. and address=#{address}
  30. </if>
  31. </where>
  32. </select>
  33. </mapper>
  • < where >标签相当于在原sql语句后补加了一个:where关键字,从底层输出的结果可以证实
  1. ==> Preparing: select id, username, birthday, sex, address from users WHERE username like concat('%', ?,'%')
  • 注意:至少有一个< if >标签通过,where关键字才会被追加,不然不会追加
  1. @Test
  2. public void testSelectOnCondition(){
  3. User u = new User();
  4. List<User> users = usersMapper.selectOnCondition(u);
  5. users.forEach(System.out::println);
  6. }
  1. Checking to see if class com.example.mapper.TestUsersMapper matches criteria [is assignable to Object]
  2. Checking to see if class com.example.mapper.UsersMapper matches criteria [is assignable to Object]
  3. Opening JDBC Connection
  4. Created connection 1340848245.
  5. Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4febb875]
  6. ==> Preparing: select id, username, birthday, sex, address from users //这时sql语句后面没有追加where
  7. ==> Parameters:
  8. <== Columns: id, username, birthday, sex, address
  9. <== Row: 1, 荷包蛋, 2002-08-23, 女, 黑河
  10. <== Row: 2, 小王, 2001-07-12, 1, 芜湖市
  11. <== Row: 3, 小张, 1999-02-22, 1, 长沙
  12. <== Row: 5, 段, 2001-03-10, 1, 太原
  13. <== Row: 6, 范成群, 2002-01-19, 1, 鲅鱼圈
  14. <== Row: 7, 学委, 2001-05-13, 2, 平顶山市
  15. <== Row: 28, 逻辑, 2010-05-18, 男, 上海
  16. <== Row: 29, 小昕, 2001-03-14, 女, 忻州
  17. <== Row: 30, 小青, 1996-11-22, 女, 沈阳市
  18. <== Total: 9
  19. Users{id=1, userName='荷包蛋', birthday=Fri Aug 23 00:00:00 CST 2002, sex='女', address='黑河'}
  20. Users{id=2, userName='小王', birthday=Thu Jul 12 00:00:00 CST 2001, sex='1', address='芜湖市'}
  21. Users{id=3, userName='小张', birthday=Mon Feb 22 00:00:00 CST 1999, sex='1', address='长沙'}
  22. Users{id=5, userName='段', birthday=Sat Mar 10 00:00:00 CST 2001, sex='1', address='太原'}
  23. Users{id=6, userName='范成群', birthday=Sat Jan 19 00:00:00 CST 2002, sex='1', address='鲅鱼圈'}
  24. Users{id=7, userName='学委', birthday=Sun May 13 00:00:00 CST 2001, sex='2', address='平顶山市'}
  25. Users{id=28, userName='逻辑', birthday=Tue May 18 00:00:00 CST 2010, sex='男', address='上海'}
  26. Users{id=29, userName='小昕', birthday=Wed Mar 14 00:00:00 CST 2001, sex='女', address='忻州'}
  27. Users{id=30, userName='小青', birthday=Fri Nov 22 00:00:00 CST 1996, sex='女', address='沈阳市'}
  28. Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4febb875]
  29. Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4febb875]
  30. Returned connection 1340848245 to pool.
  31. Process finished with exit code 0
  • 在< if >标签中的test属性中,用于条件判断的是入参的属性

    • 如果该属性不为空(对于String类型的属性,既要不等于null,又要是非空串),标签中的条件追加到原sql语句后
    • 注意:如果只是追加了一个条件,mybatis框架会自动去除该条件所带的and

测试代码

  1. package com.example.mapper;
  2. import com.example.pojo.User;
  3. import org.apache.ibatis.io.Resources;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  7. import org.junit.After;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.List;
  13. public class TestUsersMapper {
  14. //SqlSession对象
  15. SqlSession sqlSession;
  16. //mybatis动态代理对象
  17. UsersMapper usersMapper;
  18. //获取SqlSession
  19. @Before
  20. public void getSqlSession() throws IOException {
  21. //读取核心配置文件
  22. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  23. //创建SqlSessionFactory对象
  24. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
  25. //获取SqlSession
  26. sqlSession = factory.openSession();
  27. //获取mybatis动态代理对象
  28. usersMapper = sqlSession.getMapper(UsersMapper.class);
  29. }
  30. //归还SqlSession
  31. @After
  32. public void closeSession(){
  33. sqlSession.close();
  34. }
  35. @Test
  36. public void testSelectOnCondition(){
  37. User u = new User("小", null, null, null);
  38. List<User> users = usersMapper.selectOnCondition(u);
  39. users.forEach(System.out::println);
  40. }
  41. }

输出结果

  1. Checking to see if class com.example.mapper.TestUsersMapper matches criteria [is assignable to Object]
  2. Checking to see if class com.example.mapper.UsersMapper matches criteria [is assignable to Object]
  3. Opening JDBC Connection
  4. Created connection 2082509879.
  5. Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7c209437]
  6. ==> Preparing: select id, username, birthday, sex, address from users WHERE username like concat('%', ?,'%')
  7. ==> Parameters: 小(String)
  8. <== Columns: id, username, birthday, sex, address
  9. <== Row: 2, 小王, 2001-07-12, 1, 芜湖市
  10. <== Row: 3, 小张, 1999-02-22, 1, 长沙
  11. <== Row: 29, 小昕, 2001-03-14, 女, 忻州
  12. <== Row: 30, 小青, 1996-11-22, 女, 沈阳市
  13. <== Total: 4
  14. Users{id=2, userName='小王', birthday=Thu Jul 12 00:00:00 CST 2001, sex='1', address='芜湖市'}
  15. Users{id=3, userName='小张', birthday=Mon Feb 22 00:00:00 CST 1999, sex='1', address='长沙'}
  16. Users{id=29, userName='小昕', birthday=Wed Mar 14 00:00:00 CST 2001, sex='女', address='忻州'}
  17. Users{id=30, userName='小青', birthday=Fri Nov 22 00:00:00 CST 1996, sex='女', address='沈阳市'}
  18. Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7c209437]
  19. Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7c209437]
  20. Returned connection 2082509879 to pool.
  21. Process finished with exit code 0

< set >标签

作用

  • 对选中的记录的字段进行有选择的更新

    • 注意:但是至少更新一个字段

原先update标签的缺点

  1. <!--
  2. //根据id更新用户信息
  3. int update(User user);
  4. -->
  5. <update id="update" parameterType="user">
  6. update
  7. users
  8. set
  9. username=#{userName}, birthday=#{birthday}, sex=#{sex}, address=#{address}
  10. where
  11. id=#{id}
  12. </update>
  1. @Test
  2. public void testUpdate() throws ParseException {
  3. //时间字符串
  4. String dateStr = "2002-8-23";
  5. int num = usersMapper.update(new User(1, "荷包蛋", date.parse(dateStr), "女", "黑河"));
  6. sqlSession.commit();
  7. if (num == 1) {
  8. System.out.println("更新成功!");
  9. }else{
  10. System.out.println("更新失败!");
  11. }
  12. }
  • 缺点分析

    • 上述标签之所以可以按照预期正常工作,是因为我们更新了该条记录处id以外的所有字段
    • 如果只更新一个字段,例如更新birthday字段,那么除了id和birthday字段,该条记录的其他字段值全部被赋值为null
    • 除非把其他不需要更改的字段赋值为与原先一样的值,该操作十分没有必要

使用< set >标签优化

UsersMapper.java

  1. package com.example.mapper;
  2. import com.example.pojo.User;
  3. /**
  4. * 数据访问层的接口,定义对数据库完成的CRUD的操作
  5. */
  6. public interface UsersMapper {
  7. //根据给定条件有选择性的更新记录的字段
  8. int updateBetter(User user);
  9. }

UsersMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.mapper.UsersMapper">
  4. <!--
  5. //根据给定条件有选择性的更新记录的字段
  6. int updateBetter(User user);
  7. private Integer id;
  8. private String userName;
  9. private Date birthday;
  10. private String sex;
  11. private String address;
  12. -->
  13. <update id="updateBetter" parameterType="user">
  14. update
  15. users
  16. <set>
  17. <if test="userName != null and userName != ''">
  18. username=#{userName},
  19. </if>
  20. <if test="birthday != null">
  21. birthday=#{birthday},
  22. </if>
  23. <if test="sex != null and sex != ''">
  24. sex=#{sex},
  25. </if>
  26. <if test="address != null and address != ''">
  27. address=#{address},
  28. </if>
  29. </set>
  30. where
  31. id=#{id}
  32. </update>
  33. </mapper>
  • < set > 标签相当于在原先sql语句后面补加了关键字,set,此时sql语句相当于:"update XXX set"
  1. ==> Preparing: update users SET address=? where id=?
  • 注意:至少有一个< if >标签通过测试,set才会被追加

    • 这里也可以解释为什么至少要更新一个字段:如果测试条件都没有通过,也就是不更新字段
    • 此时sql语句被解析为:"update XXX where id = ?",缺少set条件,sql语句出错

  • < set >标签里的< if >标签测试条件通过后,将需要修改的字段条件拼接到原sql语句后面

    • 注意:新拼接的字段条件后面要跟上一个逗号,防止有多个条件成立,要添加多个字段,当只有一个条件成立时:mybatis框架会自动去除该逗号

测试代码

  1. package com.example.mapper;
  2. import com.example.pojo.User;
  3. import org.apache.ibatis.io.Resources;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  7. import org.junit.After;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.List;
  13. public class TestUsersMapper {
  14. //SqlSession对象
  15. SqlSession sqlSession;
  16. //mybatis动态代理对象
  17. UsersMapper usersMapper;
  18. //获取SqlSession
  19. @Before
  20. public void getSqlSession() throws IOException {
  21. //读取核心配置文件
  22. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  23. //创建SqlSessionFactory对象
  24. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
  25. //获取SqlSession
  26. sqlSession = factory.openSession();
  27. //获取mybatis动态代理对象
  28. usersMapper = sqlSession.getMapper(UsersMapper.class);
  29. }
  30. //归还SqlSession
  31. @After
  32. public void closeSession(){
  33. sqlSession.close();
  34. }
  35. @Test
  36. public void testUpdateBetter(){
  37. User u = new User();
  38. u.setId(1);
  39. u.setAddress("哈尔滨");
  40. int num = usersMapper.updateBetter(u);
  41. if(num == 1){
  42. System.out.println("更新成功!");
  43. }else{
  44. System.out.println("更新失败!");
  45. }
  46. sqlSession.commit();
  47. }
  48. }

输出结果

  1. Checking to see if class com.example.mapper.TestUsersMapper matches criteria [is assignable to Object]
  2. Checking to see if class com.example.mapper.UsersMapper matches criteria [is assignable to Object]
  3. Opening JDBC Connection
  4. Created connection 544966217.
  5. Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@207b8649]
  6. ==> Preparing: update users SET address=? where id=?
  7. ==> Parameters: 哈尔滨(String), 1(Integer)
  8. <== Updates: 1
  9. 更新成功!
  10. Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@207b8649]
  11. Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@207b8649]
  12. Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@207b8649]
  13. Returned connection 544966217 to pool.
  14. Process finished with exit code 0

mybatis 09: 动态sql --- part1的更多相关文章

  1. MyBatis的动态SQL详解

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它 ...

  2. Mybatis解析动态sql原理分析

    前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...

  3. mybatis 使用动态SQL

    RoleMapper.java public interface RoleMapper { public void add(Role role); public void update(Role ro ...

  4. MyBatis框架——动态SQL、缓存机制、逆向工程

    MyBatis框架--动态SQL.缓存机制.逆向工程 一.Dynamic SQL 为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句.最常用的就是:where和if标签 1.参考 ...

  5. 使用Mybatis实现动态SQL(一)

    使用Mybatis实现动态SQL 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 写在前面:        *本章节适合有Mybatis基础者观看* 前置讲解 我现在写一个查询全部的 ...

  6. MyBatis探究-----动态SQL详解

    1.if标签 接口中方法:public List<Employee> getEmpsByEmpProperties(Employee employee); XML中:where 1=1必不 ...

  7. mybatis中的.xml文件总结——mybatis的动态sql

    resultMap resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功. 如果sql查询字段名和pojo的属性名不一致,可以通过re ...

  8. mybatis.5.动态SQL

    1.动态SQL,解决关联sql字符串的问题,mybatis的动态sql基于OGNL表达式 if语句,在DeptMapper.xml增加如下语句; <select id="selectB ...

  9. MyBatis的动态SQL详解-各种标签使用

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有: if choose(when,otherwise) ...

随机推荐

  1. 【Unity Shader学习笔记】Unity光照基础-高光反射

    1.原理 1.1.Phong模型 计算高光反射需要表面法线.视角方向.光源方向.反射方向等. 在这四个矢量中,我们实际上只需要知道其中3个矢量即可,而第4个矢量(反射方向r)可以通过其他信息计算得到: ...

  2. 秋招如何抱佛脚?2022最新大厂Java面试真题合集(附答案

    2022秋招眼看着就要来了,但是离谱的是,很多同学最近才想起来还有秋招这回事,所以纷纷临时抱佛脚,问我有没有什么快速磨枪的方法, 我的回答是:有! 说起来,临阵磨枪没有比背八股文更靠谱的了,很多人对这 ...

  3. python基础学习5

    Python的基础学习5 内容概要 流程控制理论 if判断 while循环 内容详情 流程控制理论 # 流程控制:即控制事物执行的流程 # 执行流程的分类 1.顺序结构 从上往下按顺序依次执行 2.分 ...

  4. CSP 2021 总结

    CSP 2021 总结 PJ 开题顺序:1342 应该先做 T2 ,导致我 T2 直接看错 T1.T3 T1 :直接推规律即可,考场的想法应该正确 T3 :好家伙直接 map 走起 T2 最崩溃的来了 ...

  5. 用QT制作3D点云显示器——QtDataVisualization

    因为QT的三维显示模块QtDataVisualization已经对个人开发免费开放了,所以在制作点云,地图,表格之类的东西的时候,其实我们都不需要使用QtCharts或者QOpenGL模块了.直接使用 ...

  6. 「非软文」零基础学习TypeScript(源码开源)

    今天,这篇文章篇幅很短,主要开放我最近学习整理TypeScript源码. 源码地址 https://github.com/maomincoding/typeScript_study 更多内容请见原文, ...

  7. IDEA插件配置之Eclipse Code Formatte

    1.下载 在idea中的Plugins中下载插件 Eclipse Code Formatte,下载过之后重启. 2.配置 将自己下载的xml文件加载进来即可. 这个xml文件可自行在网上找找,有需要的 ...

  8. 8.3 如何在Windows电脑安装Java开发环境(JDK)

    下载 来到JDK官方下载界面,找到Java SE 8(简称JDK 8)后面的JDK下载,来到该界面,先同意协议,然后下载对应平台的JDK,我们这里下载Windows x64. 安装 双击安装就行了了, ...

  9. plain framework的实际应用和扩展

    首先在这里庆祝香港回归祖国的怀抱25周年,想起那年还是一个小学生戴着红领巾和胸章激动不已,实现祖国的统一是每个中华儿女从小的梦想!趁着这欢庆的日子,突然想要写些什么,其实最近也在做一些事,由于工作繁忙 ...

  10. Day03 HTML标记

    文本标题 <h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标题</h3> <h4>四级标题< ...