动态SQL

官方文档已经写的非常详细

动态Sql是指根据不同的条件生成不同的SQL语句

之前是手动拼接的,拼接sql语句是很麻烦的

四个标签:

  • if
  • choose(when,oherwise)
  • trim(where,set)
  • foreach

动态SQL环境搭建

  • 数据库
  • maven导包
  • 实体类
  • Mapper.xml
  • 核心配置文件
    • setting驼峰命名转换
  • 工具类
    • IDutils通过UUID实现随机ID

都是比较常用的套路

开始

  1. 创建数据库

  2. Maven导包

    1. <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency>
      </dependencies>
      
  3. 编写POJO实体类

    1. @Data
      @NoArgsConstructor
      @Alias("Blog")
      public class Blog {private String id;private String title;private String author;private Date createTime;//添加驼峰命名映射setting/*这个名字会映射成create_time*//*mapUnderscoreToCamelCase*/private int views;
      }
      
  4. 编写接口以及接口映射

    1. 编写好实体类就写好对应的接口,接口写好写映射,然后把映射添加到核心配置文件中去

    2. public interface blogMapper {@Select("select * from blog")List<Blog> getblogs();int addBook(Blog blog);
      }
      
    3. 暂时写了两个接口,一个使用注解一个使用xml

    4. <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.haoyun.dao.blogMapper"><insert id="addBook" parameterType="Blog">insert into mybatis.blog (id,title,author,create_time,views)values (#{id},#{title},#{author},#{createTime},#{views});</insert></mapper>
      
    5. 因为添加了驼峰命名的设置,所以这里传递参数是填写的createTime

  5. 编写核心配置文件

    1. 使用的是外部配置文件

    2. driver  = com.mysql.cj.jdbc.Driver
      url= jdbc:mysql://localhost:3306/mybatis?useSSL=false
      -TRUE&useUnicode=true&characterEncoding=UTF-8
      username  =root
      password = 123456
      
    3. <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration><!--引入外部配置文件--><properties resource="db.properties"/><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><package name="com.haoyun.POJO"/></typeAliases><!--可以写多套环境配置,s复数,可以编写多套配置环境,但是default只能选择一套 --><environments default="Test"><!--这样就会选择Test的环境配置--><environment id="Test"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--映射--><mappers><mapper class="com.haoyun.dao.blogMapper"/><mapper resource="blogMapper.xml"/></mappers></configuration>
      
    4. 要注意setting标签编写的位置

    5. 设置 mapUnderscoreToCamelCase为true,名字不要打错

    6. https://mybatis.org/mybatis-3/zh/configuration.html#settings

  6. 编写工具类

    1. MybatisUtil这个工具类使用过好多次了,用来创建sqlsession

    2. public class MybatisUtil {private static SqlSessionFactory sqlSessionFactory = null;static {InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream("mybatis-config.xml");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}public static SqlSession getSqlSession(){return sqlSessionFactory.openSession();}
      }
      
    3. 再写一个随机生成ID的,使用UUID方法

    4. public class IDutils {public static String getId(){return UUID.randomUUID().toString().replaceAll("-","");}
      }
      
    5. 将 “-” 替换为 “” 空

    6. 1a19b16580bb46588863d96fa4822d4f测试得到的id

  7. 环境整体结构

    1. 测试

    2. public class blogTest {@Testpublic void Test() {SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);List<Blog> getblogs = mapper.getblogs();for (Blog getblog : getblogs) {System.out.println(getblog);}sqlSession.close();}@Testpublic void TestInsert() {SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);Blog blog = new Blog();blog.setId(IDutils.getId());blog.setTitle("TestTitle");blog.setAuthor("TestAuthor");//生成时间记得选择util包的Dateblog.setCreateTime(new Date());blog.setViews(1200);mapper.addBook(blog);sqlSession.commit();sqlSession.close();}@Testpublic void IDutilsTest() {System.out.println(IDutils.getId());}}
      

动态SQL之IF语句

就是再Mapper.xml中添加if判断,实现sql的拼接,可以判断是否传递了对应列的参数来指定拼接对应的sql

流程:

  1. 添加接口方法

  2. 设置mapper.xml

    1. 加入if判断
  3. 测试

  4. 添加接口发方法

    1. List<Blog> queryBlogIF(Map map);
      
  5. 设置mapper.xml

    1.     <select id="queryBlogIF" parameterType="map" resultType="Blog">select * from blog<where><if test="title!= null">and title = #{title}</if><if test="author != null">and author =#{author}</if></where></select>
      
    2. 参数类型为map,返回值类型为Blog,这个添加了重命名

    3. 为了保证if条件都不符合,不进行拼接sql语句的情况,不能写成这样,这样拼接上是直接跟着and或or的,所以在if外要包上一层

    4. ​ select * from blog where

    5. 如果传递了参数,进行判断,然后拼接sql

  6. 测试

    1. @Test
      public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();hashMap.put("title","sadfasdf");hashMap.put("author","l");List<Blog> blogs = mapper.queryBlogIF(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();}
      
    2. 结果

    3. 可以选择传入一个空的hashMap,查询的就是全表的信息

trim(where,set)

trim 切除

这个主要的功能就是,拼接字符串,然后删除语句后缀的逗号

<select id="updateBlog" parameterType="map" >update blog<set><if test="title != null">title = #{title},</if><if test="author != null">author = #{author},</if></set>where id = #{id}
</select>

根据编写内容不同选择不同的标签,这里是更新,所以加入了set标签,使用方法也是一样的,只是这里拼接到where的时候会取除末尾的标签中语句的逗号,当然,两个if都没用上,会直接报错的,因为set之后直接拼接where,造成语法错误

@Test
public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();hashMap.put("title","sadsdf");hashMap.put("author","test");hashMap.put("id","1");mapper.updateBlog(hashMap);sqlSession.commit();sqlSession.close();
}

最后author末尾的逗号是被消除了

choose(when,otherwise )

choose 选择

when 什么情况下

otherwise 否则

规则有点像switch,只去匹配case中的一个值,唯一不同的就是otherwise必须添加参数,如果走了where就不会走otherwise,where都没走就会走otherwise,执行顺序是从上往下执行的,先判定上面的where

choose语句

    <select id="queryBlogChoose" parameterType="map" resultType="Blog">select * from blog<where><choose><when test="title != null">and title = #{title}</when><when test="author!= null">and author = #{author}</when><otherwise>and views = #{views}</otherwise></choose></where></select>

多种情况测试

  1. 不填参数

  2. @Test
    public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();//hashMap.put("title","sadfasdf");//hashMap.put("author","l");//hashMap.put("views","55");List<Blog> blogs = mapper.queryBlogChoose(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();
    }
    
  3. 自动的添加了views条件但是parameter为null

  4. 没查询出来

  5. hashMap.put("views",10);
    
  6. 所以前面的when没有参数就会添加otherwise中的语句

  7. 加入中间when值

  8. hashMap.put("author","l");
    hashMap.put("views",10);
    
  9. 加入了中间的author when判断和otherwise判断

  10. 但是只执行了when的语句,otherwise并没有执行

  11. when优先级

  12. hashMap.put("title","sadfasdf");
    hashMap.put("author","l");
    hashMap.put("views",10);
    
  13. 三条都加入了

  14. 但是只执行了第一条

  15. 所以第一条的优先级最高

总结:

  • 什么参数都不加的情况下会选择otherwise中的语句
  • 第一个多条when条件,从上往下判断,执行排在上面的
  • 只选择一条,包括otherwise

共同的父亲trim

如果前置有set关键字,就会删除无关的逗号,prefix 前缀

指定的是一个where,如果存在就会删除指定的内容

这是定制化sql用的一些东西

SQL片段

有一些重复的语句,可以提取出代码片段,实现sql语句的复用

<sql id="if_title_author"><if test="title!= null">and title = #{title}</if><if test="author != null">and author =#{author}</if>
</sql><select id="queryBlogIF" parameterType="map" resultType="Blog">select * from blog<where><include refid="if_title_author"/></where>
</select>

最好sql片段不要编写太复杂的事情,要不然重用效率就变低了

不要存在where标签,where是要根据条件语句来查询的加入就不好实现复用

foreach

<select id="queryBlogForEach" parameterType="map" resultType="Blog">select * from blog<where><foreach collection="ids" item="id" open="and (" close=")" separator="or">id = ${id}</foreach></where>
</select>

传入一个map类型参数,返回值是一个Blog类型

collection 传递进一个集合,集合的名称为ids,那么用map传递参数的时候就要对应ids名进行传参

里面的每个元素是id,传递了集合就会进行自动的遍历集合,传递参数进id中,

open开始,加入where是为了解决select * from where 1=1 后面必须跟指定条件成立的语句,要不然动态sql没有进入foreach就会变成 select * from where 导致语句错误,加入where标签,还能根据判断去除不必要的and或or

这里就是open开始,填装了一个and (,注意,and和( 之间是有一个空格的,要不然where会识别不出来

在日志中查看得出的结果就是这样

本来用来连接其他条件的语句,不连接其他条件,and没有被去除,导致语句出错

close foreach结束时添加

separator 分隔符,用来分隔集合中元素的分隔符

最后给集合元素传参

@Test
public void queryBlogForEachTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();ArrayList<String> arrayList = new ArrayList<String>();arrayList.add("1");arrayList.add("2");arrayList.add("3");hashMap.put("ids",arrayList);List<Blog> blogs = mapper.queryBlogForEach(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.commit();sqlSession.close();
}

总结:

动态sql,本质还是sql,只是在sql层面,去执行一个逻辑代码,按照sql格式进行拼接,排列组合,去除不必要的字符

先在Mysql中写出完整的sql,再去修改实现动态sql,实现通用

多去看官方文档

怎么使用普通的sql查询还是不够的,需要多去了解更深层次的知识

  • mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化

Mybatis-动态SQL-trim-choose-foreach相关推荐

  1. MyBatis动态SQL之<foreach>用法

    目录 一.foreach元素的属性 二.collection属性值的三种情况 三.代码示例 四.相关错误 一.foreach元素的属性 collection: foreach的对象,作为入参,对象为l ...

  2. MyBatis动态sql之choose(when、otherwise)用法

    if标签是与(and)的关系,只要test中的表达式为 true,就会执行 if 标签中的条件;而 choose 是或(or)的关系,并不想应用所有的条件,而只是想从多个选项中选择一个. choose ...

  3. Mybatis动态sql中的foreach标签的使用

    foreach 标签一般用于遍历集合,构建in条件语句或者批量操作语句 <insert id="batchSave" parameterType="java.uti ...

  4. MyBatis动态SQL之 set 和 trim标记的使用示例

    2019独角兽企业重金招聘Python工程师标准>>> 和之前的where一样,set和trim也是智能标记 在之前的user.xml中添加 <update id=" ...

  5. MyBatis动态SQL(认真看看, 以后写SQL就爽多了)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:cnblogs.com/homejim/p/9909657. ...

  6. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦 ...

  7. 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL:

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 阿进的写字台 来源 | cnblogs.com ...

  8. MyBatis动态SQL,写SQL更爽

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客: ...

  9. 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达今日推荐:2020年7月程序员工资统计,平均14357元,又跌了,扎心个人原创100W+访问量博客:点击前往,查看更多 整理 ...

  10. Mybatis 动态Sql语句《常用》

    MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉 ...

最新文章

  1. WEB标准页面CSS命名参考
  2. go 获取内核个数_图解Go运行时调度器
  3. python爬虫今日头条街拍美图开发背景_分析Ajax请求并抓取今日头条街拍美图:爬取详情页的url与实际页面上显示不符...
  4. 《社交网站界面设计(原书第2版)》——2.11 提问
  5. mysql 迁移到tidb_通过从MySQL迁移到TiDB来水平扩展Hive Metastore数据库
  6. 02-Django基础知识
  7. Java基础复习——访问权限
  8. mysql 参数 innodb_flush_log_at_trx_commit
  9. linux dns服务无效,Linux下搭建DNS服务器及踩坑
  10. 本地运行 MAYA 帮助文档
  11. 两种“新型”的javaweb后门(jspx和Java Logger)
  12. WeaveSocket框架-Unity太空大战游戏-通信协议-2
  13. 阿里云IoT千里传音之声连网互动营销服务,首次亮相!
  14. 2021年最新Android面试点梳理,成功入职腾讯
  15. 百度人脸识别API调用实现
  16. live.com与live.cn邮箱收不到QQ绑定激活信的解决方法
  17. word右顶格_word顶格书写 WORD如何顶格
  18. eclipse配置python解析器_Eclipse中配置Python环境
  19. D. Equalize Them All
  20. imx6 添加matrix keypad

热门文章

  1. 腾讯游戏盒子当中的游戏医生功能分析
  2. Vivado识别Flash型号失败
  3. Geotools中蜂巢的实现
  4. tp5.1 获取表里的所有数据_携程机票数据仓库建设之路
  5. Unpacker ExeCryptor 2.x.x. beta1,beta2 byRSI
  6. 【转载】程序员如何爱护眼睛
  7. 外贸crm客户管理系统有什么优势和特点
  8. android大智慧安装目录,大智慧新一代目录文件结构,及备份方法
  9. VOC和COCO数据集
  10. Docker之镜像底层原理