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(12)

    25W/m 76% Most of us have formed an unrealistic picture of life on a desert island. We sometimes ima ...

  2. Linux:grep命令详解

    grep grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具, ...

  3. spinlock变量没有初始化

    http://blog.csdn.net/longwang155069/article/details/52224284

  4. Ubuntu连接手机步骤

    第一次使用adb之前,需要在home/.android里新建adb_usb.ini文件:0x1782. 注:adb已在安装系统后装好,手机要处于开机状态 查看设备命令: $ adb devices 正 ...

  5. couldn't import dot_parser

    这个错误,你不要信它,实际可以画图了.害我又降级安装,真是气死了.

  6. stark组件02

    1.怎么在显示页面添加新字段(a标签)?在admin.py下注册就好了 当我们需要在admin页面添加新的a标签时,需要引入一个类似safe功能的模块 from django.utils.safest ...

  7. Apache下配置Openstack Horizon (转)

    非常详尽的Horizon配置介绍,转自 dev.cloudwatt.com Deploy Horizon from source with Apache and SSL Some companies ...

  8. Infinite size of Hypothesis set and growth function

    We want: 根据Hoeffding: 但是M是无穷大的,是否可以找到一个有穷大的m_H去替代无穷大的M? 思考:M从何而来。 Hset里有M个h,对于每个Data,只要存在一个h会造成Bad,即 ...

  9. BZOJ1066 SCOI2007 蜥蜴 【网络流-最大流】

    BZOJ1066 SCOI2007 蜥蜴 Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离 ...

  10. .NET Core 和 .NET Framework 中的 MEF2

    MEF,Managed Extensibility Framework,现在已经发布了三个版本了,它们是 MEF 和 MEF2. 等等!3 去哪儿了?本文将教大家完成基于 MEF2 的开发.   ME ...