先说下我的梦想,大学的时候一直想着是能开店卖胡辣汤,到目前依然还是我的梦想,上周一家出版社联系我问我有没有时间可以合作出书,这也是我的梦想之一,想了想还是放弃了,至少觉得目前不行,毕竟工作还不到五年,出书我可不想误人子弟,还有就是将来能办个培训班,这个我觉得还不错,所以也是我坚持写博客的原因之一。装逼结束,开始正题。

计划着能在年前把MyBatis学个差不多,所以上周是逼自己一把,连着3天一直在看Mybatis.前面把MyBatis中的表映射、列映射和增删改查大致了解了一下,今天主要学习动态sql。动态sql说白了就是sql拼接,看怎么拼接方便好用。

一、if

比如在一些查询功能,当输入值时模糊查询,不输入值时查询全部。这样的话就需要拼接where,一般遇到这样的我先会在sql后面加where 1=1.这样不为where和and在揪心。

  1. <select id="finduserbylikename" parameterType="string" resultMap="courseResult">
  2. select * from course where 1=1
  3. <if test="_parameter!=null and _parameter!=''">
  4. and name like #{_parameter}
  5. </if>
  6. </select>
  7. <select id="finduserbylikename2" parameterType="map" resultMap="courseResult">
  8. <bind name="pattern" value="'%' + _parameter.name + '%'" />
  9. select * from course where 1=1
  10. <if test="_parameter.name!=null and _parameter.name!=''">
  11. and name like #{pattern}
  12. </if>
  13. </select>
  1. String resource = "Config.xml";
  2. //使用MyBatis提供的Resources类加载mybatis的配置文件(它也加载关联的映射文件)
  3. Reader reader = Resources.getResourceAsReader(resource);
  4. //构建sqlSession的工厂
  5. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
  6. //创建能执行映射文件中sql的sqlSession
  7. SqlSession session = sessionFactory.openSession(true);
  8. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.finduserbylikename";
  9. List<Course> courses=session.selectList(statement, "%J%");
  10. System.out.println(courses.size());
  11. for(int i=0;i<courses.size();i++)
  12. {
  13. System.out.println(courses.get(i).toString());
  14. }
  15. statement="Cuiyw.MyBatis.DBMapping.UserMapper.finduserbylikename2";
  16. Map<String,Object> map=new HashMap<String,Object>();
  17. map.put("name", "J");
  18. courses=session.selectList(statement, map);
  19. System.out.println(courses.size());
  20. for(int i=0;i<courses.size();i++)
  21. {
  22. System.out.println(courses.get(i).toString());
  23. }
  24. session.close();

上面用了两种传参数的方式,一个时string,一个是map,用map可以传多个参数。还有就是在第二个使用了bind,这样可以在sql中增加%%,参数中可以不带。这里记下自己踩的一个坑。

  1. <select id="finduserbylikename" parameterType="string" resultMap="courseResult">
  2. select * from course where 1=1
  3. <if test="name!=null and name!=''">
  4. and name like #{name}
  5. </if>
  6. </select>

我用上面的运行报出了下面的错误,我开始以为是like后面的#{name}错误,后来查了百度才知道是if里面的。

  1. There is no getter for property named 'name' in 'class java.lang.String'
  1. <select id="finduserbylikename" parameterType="string" resultMap="courseResult">
  2. select * from course where 1=1
  3. <if test="_parameter!=null and _parameter!=''">
  4. and name like #{name}
  5. </if>
  6. </select>

二、choose (when, otherwise)

做项目也经常会遇到左边一个下拉框选择搜索类型,按什么类型搜索,右边一个文本框,输入搜索关键字,点查询搜索。如果遇到这种情况,用choose是再合适不过了。

  1. <select id="findcard" parameterType="map" resultMap="cardResult">
  2. <bind name="pattern" value="'%' + _parameter.value + '%'" />
  3. select * from card where 1=1
  4. <choose>
  5. <when test="type=='city'">
  6. AND city like #{pattern}
  7. </when>
  8. <when test="type=='address'">
  9. AND address like #{pattern}
  10. </when>
  11. <otherwise>
  12. AND city like #{pattern} or address like #{pattern}
  13. </otherwise>
  14. </choose>
  15. </select>
  1. String resource = "Config.xml";
  2. //使用MyBatis提供的Resources类加载mybatis的配置文件(它也加载关联的映射文件)
  3. Reader reader = Resources.getResourceAsReader(resource);
  4. //构建sqlSession的工厂
  5. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
  6. //创建能执行映射文件中sql的sqlSession
  7. SqlSession session = sessionFactory.openSession(true);
  8. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcard";
  9. Map<String,Object>map=new HashMap<String,Object>();
  10. map.put("type", "other");
  11. map.put("value", "深");
  12. List<Card> cards=session.selectList(statement, map);
  13. System.out.println(cards.size());
  14. for(int i=0;i<cards.size();i++)
  15. {
  16. System.out.println(cards.get(i).toString());
  17. }
  18. statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcard";
  19. map=new HashMap<String,Object>();
  20. map.put("type", "city");
  21. map.put("value", "深");
  22. cards=session.selectList(statement, map);
  23. System.out.println(cards.size());
  24. for(int i=0;i<cards.size();i++)
  25. {
  26. System.out.println(cards.get(i).toString());
  27. }
  28. session.close();

三、trim (where, set)

prefix:在trim标签内sql语句加上前缀。
suffix:在trim标签内sql语句加上后缀。
suffixOverrides:指定去除多余的后缀内容,如:suffixOverrides=",",去除trim标签内sql语句多余的后缀","。
prefixOverrides:指定去除多余的前缀内容

有这样一种情况,大家应该也很常见,比如对对象的修改操作,可能有时需要根据根据不同的条件进行修改不同的列,如果比如根据id修改name,根据id修改age,这样不能每个都写一个sql,这样也太不灵活了,于是trim出现了。

  1. <update id="updatecard" parameterType="map">
  2. update card
  3. <trim prefix="set" suffixOverrides=",">
  4. <if test="_parameter.cardNo!=null and _parameter.cardNo!=''">
  5. cardNo = #{cardNo},
  6. </if>
  7. <if test=" _parameter.city!=null and _parameter.city!=''">
  8. city = #{city},
  9. </if>
  10. </trim>
  11. <trim prefix="WHERE" prefixOverrides="and|or">
  12. <if test=" _parameter.id!=null and _parameter.id!=''">
  13. and id = #{id}
  14. </if>
  15. <if test=" _parameter.address!=null and _parameter.address!=''">
  16. and address = #{address}
  17. </if>
  18. </trim>
  19. </update>

有了trim可以很方便的写出where、set子句,而不用担心set子句的逗号,where子句的and和or。这里有一个地方要注意,也是我踩过的坑,我在写prefixOverrides时中间的O写成了小写,然后就报错了,还有set子句中每个后面增加一个逗号。

  1. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.updatecard";
  2. Map<String,Object> map=new HashMap<String,Object>();
  3. map.put("cardNo", "100002");
  4. map.put("city", "广州");
  5. map.put("id", "1");
  6. int result=session.update(statement, map);
  7. System.out.println(result);

四、foreach

还有一种情况,这篇都是情况,举栗子,我们有时候需要使用in查询,通常传的是一个collection集合,那改怎么样拼接呢?当然是foreach.

item表示集合中每一个元素进行迭代时的别名,
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔 符,
close表示以什么结束

  1. <select id="findcardbycardnos" parameterType="map" resultMap="cardResult">
  2. select * from card where cardNo in
  3. <foreach collection="nos" index="index" item="item" open="(" separator="," close=")">
  4. #{item}
  5. </foreach>
  6. </select>
  1. SqlSession session = sessionFactory.openSession(true);
  2. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
  3. List nos = new ArrayList();
  4. nos.add("100001");
  5. nos.add("100002");
  6. nos.add("100003");
  7. Map<String,Object> map=new HashMap<String,Object>();
  8. map.put("nos", nos);
  9. List<Card> cards=session.selectList(statement,map);
  10. for(int i=0;i<cards.size();i++)
  11. {
  12. System.out.println(cards.get(i).toString());
  13. }

这里使用的map进行的传参,如果是单个参数的话可以用Array数组或List类型,使用List时,需要parameterType和collection都改为list。使用数组时,parameterType="arraylist",collection="array"。

list

  1. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
  2. List nos = new ArrayList();
  3. nos.add("100001");
  4. nos.add("100002");
  5. nos.add("100003");
  6. Map<String,Object> map=new HashMap<String,Object>();
  7. map.put("nos", nos);
  8. List<Card> cards=session.selectList(statement,nos);
  9. for(int i=0;i<cards.size();i++)
  10. {
  11. System.out.println(cards.get(i).toString());
  12. }
  1. <select id="findcardbycardnos" parameterType="list" resultMap="cardResult">
  2. select * from card where cardNo in
  3. <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
  4. #{item}
  5. </foreach>
  6. </select>

array

  1. String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
  2. List<Card> cards=session.selectList(statement,new String[] {"100001","100002","100003"});
  3. for(int i=0;i<cards.size();i++)
  4. {
  5. System.out.println(cards.get(i).toString());
  6. }
  1. <select id="findcardbycardnos" parameterType="arraylist" resultMap="cardResult">
  2. select * from card where cardNo in
  3. <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
  4. #{item}
  5. </foreach>
  6. </select>

MyBatis之基于XML的动态SQL的更多相关文章

  1. Mybatis基于xml的动态sql实现

    动态sql可以很方便的拼接sql语句,主要用于复合条件查询: 主要通过这几个标签实现: if 标签: where 标签 choose标签: foreach标签: if 标签: <select i ...

  2. MyBatis学习 之 三、动态SQL语句

    目录(?)[-] 三动态SQL语句 selectKey 标签 if标签 if where 的条件判断 if set 的更新语句 if trim代替whereset标签 trim代替set choose ...

  3. Mybatis 系列9-强大的动态sql 语句

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  4. Mybatis之关联查询及动态SQL

    前言 实际开发项目中,很少是针对单表操作,基本都会联查多表进行操作,尤其是出一些报表的内容.此时,就可以使用Mybatis的关联查询还有动态SQL.前几篇文章已经介绍过了怎么调用及相关内容,因此这里只 ...

  5. MyBatis(4):动态SQL

    什么是动态SQL MyBatis的一个强大特性之一通常是它的动态SQL能力.如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的 ...

  6. 【转载】 mybatis入门系列四之动态SQL

    mybatis 详解(五)------动态SQL 目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when, ...

  7. MyBatis框架基于XML的配置

    什么是MyBatis? 答:它是一个持久层框架 说的太简单了吗?那让我们来看一下官方的文档描述: MyBatis有什么作用呢? 1.持久层的零实现 2.可以自动将数据封装到对象里面不需要手工编写映射的 ...

  8. MyBatis框架(6)动态sql

    本次全部学习内容:MyBatisLearning   什么是动态sql:     mybatis的核心,对sql进行灵活的操作,通过对表达式的判断,对sql灵活的拼接 在之前小案例的基础上我们先进行简 ...

  9. mybatis学习(九)——动态sql

    MyBatis 的强大特性之一便是它的动态 SQL.可以根据不同条件拼接 SQL 语句. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似.主要由以下几种元素. if wh ...

随机推荐

  1. thinkphp 官方文件执行引入流程

    官方手册上的执行流程图: 系统流程 用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载 ...

  2. leetcode — word-break

    import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Source : https://oj.l ...

  3. 安卓电量优化之AlarmManager使用全部解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.AlarmManager概述 AlarmManager是安卓系统中一种系统级别的提示服务,可以在我们设定时间或者周期性的执行一个intent,这 ...

  4. git和github新手安装使用教程(三步入门)

    git和github新手安装使用教程(三步入门) 对于新手来说,每次更换设备时,github的安装和配置都会耗费大量时间.主要原因是每次安装时都只关心了[怎么做],而忘记了记住[为什么].本文从操作的 ...

  5. g4e基础篇#3 Git安装与配置

    g4e 是 Git for Enterprise Developer的简写,这个系列文章会统一使用g4e作为标识,便于大家查看和搜索. 章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git ...

  6. mysql目录迁移 更改mysql的存储目录

    元旦节刚过完回来,忙了一天,现在的时间剩余不是很充足,所以更新简短的文章一篇! 正文: 正常情况下mysql的存储目录都是在/var/lib/mysql/下的,那么怎么将存储位置改到/data_mys ...

  7. [Spark內核] 第42课:Spark Broadcast内幕解密:Broadcast运行机制彻底解密、Broadcast源码解析、Broadcast最佳实践

    本课主题 Broadcast 运行原理图 Broadcast 源码解析 Broadcast 运行原理图 Broadcast 就是将数据从一个节点发送到其他的节点上; 例如 Driver 上有一张表,而 ...

  8. 如何一条sql语句查找表中第二大值

    例1: 一个Customer表,一个字段Value,现请问如何查到Value中第二大的值 select max(value) from Customer where value < (selec ...

  9. Python进阶内容(四)--- 迭代器(Iterator)与生成器(Generator)

    迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...

  10. Nginx配置反向代理

    Nginx可做web服务器,也可做负载均衡使用. 反向代理:应用服务器不直接提供服务,通过nginx服务器处理请求, 转发到代理服务器(Tomcat,Nginx,Apache等) 获取响应交给客户端, ...