MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑。

例如,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息

MyBatis中用于实现动态SQL的元素主要有:

  • if
  • choose(when,otherwise)
  • trim
  • where
  • set
  • foreach
示例mapper.xml:
 
  1. <select id="findActiveBlogLike"
  2. parameterType="BLOG" resultType="BLOG">
  3. SELECT * FROM BLOG
  4. WHERE
  5. <trim prefix="WHERE" prefixOverrides="AND |OR ">
  6. <choose>
  7. <when test="title != null">
  8. AND title like #{title}
  9. </when>
  10. <when test="author != null and author.name != null">
  11. AND title like #{author.name}
  12. </when>
  13. <otherwise>
  14. AND featured = 1
  15. </otherwise>
  16. </choose>
  17. </trim>
  18. </select>
  19. <update id="updateAuthorIfNecessary"
  20. parameterType="Author">
  21. update Author
  22. <trim prefix="where" prefixOverrides=",">
  23. <set>
  24. <if test="username != null">username=#{username},</if>
  25. <if test="password != null">password=#{password},</if>
  26. <if test="email != null">email=#{email}</if>
  27. </set>
  28. where id=#{id}
  29. </trim>
  30. </update>
但是问题来了,如果我们没有实体怎么办?如上代码,都是关联实体Author,BLOG。
更进一步,如果我们连字段和表名都是程序运行时产生的,那么在Mybatis中,我们的mapper.xml又该如何写呢?
 
不要说这种需求很少,实际上很多灵活性和扩展性要求比较高的应用,物理模型不确定,也即是你的表结构不确定,甚至连表名字都不确定,基本上sql中的每一个字母都不是写死的。
 
我现在就遇到了这种需求,简单描述如下:
事先定义好了很多数据集的信息模型,针对这些信息模型生成物理模型。而我们需要针对这些物理模型进行操作。而这些数据集一旦更新,信息模型以及物理模型都要变动,所以事先不可能完全确定物理表结构等等信息。此时应该怎么在mybatis中进行处理呢?
 

翻阅mybatis文档,在一个不起眼的地方发现update标签有一个属性statementType,根据jdbc的经验,这应该是控制sql预编译还是非预编译的,如果sql执行是预编译的,那么动态传入字段名,表名之类的,显然

是不行的,所以你必须改成非预编译的。

两者有什么区别呢?如果是预编译的,那么系统在初始化时就会读取这段sql代码,将指定的实体类中的字段替换了类似#{}这样的语句,就是形成了类似这样的语句:

"select * from tableName where id=?" 这个时候你在系统运行时再想向这句sql中替换tableName或者id,结果可想而知。如果是非预编译呢,结果刚好相反,他会在系统运行时才会去生成这样类似的语句。此时就可以去替换这些动态的字段或者表名之类。这样在结合之前所讲的返回类型的设置,我们的问题就解决了。

我们可以不用设定参数和返回类型的实体类,只需要形成一个动态的表名和字段名的列表类。就可以动态对那些未知的物理模型进行操作.如下代码可作参考:

  1. <select id="queryMetaList" resultType="Map" statementType="STATEMENT">
  2. select * from ${tableName} t where
  3. <foreach item="item" index="index" collection="field" open=" "
  4. separator="and" close=" ">
  5. <choose>
  6. <when test="item.fieldType == 'DATE' and item.dateQueryFlag == 0">
  7. ${item.fieldCode} between
  8. to_date('${item.fieldValue}','yyyy-mm-dd
  9. hh24:mi:ss')
  10. </when>
  11. <when test="item.fieldType == 'DATE' and item.dateQueryFlag == 1">
  12. to_date('${item.fieldValue}','yyyy-mm-dd
  13. hh24:mi:ss')
  14. </when>
  15. <when test="item.fieldItemCode != null and item.fieldItemCode != ''">
  16. ${item.fieldCode} =
  17. '${item.fieldItemCode}'
  18. </when>
  19. <otherwise>
  20. ${item.fieldCode} =
  21. '${item.fieldValue}'
  22. </otherwise>
  23. </choose>
  24. </foreach>
  25. </select>
注:会有sql注入危险,代码中要处理。
 
另外,注意返回值,在mybatis中,无论你指定还是不指定返回类型,mybatis都会默认的先将查询回的值放入一个hashMap中(如果返回的值不止一条就是一个包含hashMap的list)。这其中的区别在于,如果你指定了返回类型,mybatis将会根据返回类型的实体类来从hashMap中获取值并set到这个实体类中。如果不指定就默认返回一个HashMap<String,Object>(List<HashMap<String,Object>>)。
 
我们没有实体,当然就不要指定返回值,默认接受处理List<HashMap<String,Object>>结构的返回值即可。

Mybatis动态构建Sql(无实体类)的更多相关文章

  1. 模拟实现MyBatis中通过SQL反射实体类对象功能

    话不多说,直接上干货! package cn.test; import java.lang.reflect.Method; import java.sql.Connection; import jav ...

  2. Mybatis之动态构建SQL语句

    今天一个新同事问我,我知道如何利用XML的方式来构建动态SQL,可是Mybatis是否能够利用注解完成动态SQL的构建呢?!!答案是肯定的,MyBatis 提供了注解,@InsertProvider, ...

  3. 通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis核心原理

    本文将通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis原理 1.平常我们是如何使用Mapper的 先写一个简单的UserMapper,它包含一个全表查询的方法,代码如下 pub ...

  4. mybatis的基本配置:实体类、配置文件、映射文件、工具类 、mapper接口

    搭建项目 一:lib(关于框架的jar包和数据库驱动的jar包) 1,第一步:先把mybatis的核心类库放进lib里

  5. 使用MyBatis的Generator自动创建实体类和dao的接口与xml

    在实际的项目中其实建立数据库和设计数据库的时候特别重要,而等数据库设计完成之后,根据数据库创建实体类的工作就特别麻烦和繁琐了,不仅很麻烦,而且很浪费时间,不做又不行,这次就找到了一个简单的方法可以让m ...

  6. MyBatis——解决字段名与实体类属性名不相同的冲突

    原文:http://www.cnblogs.com/xdp-gacl/p/4264425.html 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况 ...

  7. MyBatis解决字段名与实体类属性名不相同的冲突(四)

    一.创建表和表数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no ), order_price FLOA ...

  8. Mybatis解决字段名与实体类属性名不相同的冲突

    在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突. 一.准备演示需要使用的表和数据 CREATE TAB ...

  9. mybatis中映射文件和实体类的关联性

    mybatis的映射文件写法多种多样,不同的写法和用法,在实际开发过程中所消耗的开发时间.维护时间有很大差别,今天我就把我认为比较简单的一种映射文件写法记录下来,供大家修改建议,争取找到一个最优写法~ ...

随机推荐

  1. New Concept English three (22)

    34w 54 Some plays are so successful that they run for years on end. In many ways, this is unfortunat ...

  2. C语言动态库和静态库的使用及实践

    转自:https://www.cnblogs.com/CoderTian/p/5902154.html  1.C语言中的链接器 (1)每个 C 语言源文件被编译后生成目标文件,这些目标文件最终要被链接 ...

  3. Xcode 8 插件安装

    1.删除旧插件 cd ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-in rm -rf ../Plug-ins 2.Xcode重 ...

  4. Linux:数据流重定向

    1)垃圾桶黑洞 /dev/null command > /dev/null 2)stdout与stderr写入同一个文件 command > filename >& comm ...

  5. phpstorm、webstorm配置less编译器

    1. node.js 安装包    https://nodejs.org/en/download/ 1) 安装js解析器node.js.直接下一步就ok了. 2) 将npm压缩包解压,找到里面的les ...

  6. Android学习笔记之Android Studio下创建menu布局文件

    1.创建menu文件夹 Android Studio项目中如果没有menu文件夹,在res文件夹右键,new-Android resource directory: 则会弹出下图对话框,在Resour ...

  7. MVC MVVM和传统三层的理解

    才学疏浅,请勿喷,如果有理解不对的地方请留言 其实,每个小小的程序员都有个毛病,就是反复写一个东西会觉得这个东西没有新意. 就像让你写三层,你却还是觉得想写MVC模式. 软件小公司做B/S的大部分还是 ...

  8. VS2013 tips

    1.创建一个connection时会自动产生一个localdb数据库文件,可以通过Server Explorer窗口查看这个localDB,注意,是Server Explorer窗口,而不是SQL S ...

  9. Spring配置--Aop配置详情

    首先我们来看一下官方文档所给我们的关于AOP的一些概念性词语的解释: 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象.事务管理是J2EE应用中一个关于横切关注点的很好的例子.在 ...

  10. BZOJ1260 CQOI2007 涂色paint 【区间DP】

    BZOJ1260 CQOI2007 涂色paint Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字 ...