ibatis 中动态SQL查询和动态标签嵌套的使用
ibatis 动态查询
对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate、JPA 这样的一站式对象 / 关系映射(O/R Mapping)解决方案盛行之前,iBaits 基本是持久层框架的不二选择。即使在持久层框架层出不穷的今天,iBatis 凭借着易学易用、轻巧灵活等特点,也仍然拥有一席之地。尤其对于擅长 SQL 的开发人员来说,iBatis 对 SQL 和存储过程的直接支持能够让他们在获得 iBatis 封装优势的同时而不丧失 SQL 调优的手段,这是 Hibernate/JPA 所无法比拟的。若要了解、学习ibatis,请看 iBatis开发环境搭建和示例 。
在项目开发的过程中,肯定会遇到需要根据需求动态组装sql 语句的时候,这时,ibatis的动态查询功能应运而生。
使用动态查询是iBatis一个非常强大的功能。有时你已经改变WHERE子句条件的基础上你的参数对象的状态。在这种情况下的iBATIS提供了一组可以映射语句中使用,以提高SQL语句的重用性和灵活性的动态SQL标签。动态标签的作用是动态构建SQL语句,根据不同的一元或二元运算条件构建复杂的SQL语句,这功能非常好,这样就可以把写的BO层的SQL语句构造移值到SQL MAP 文件里。例如:
select id="findUser" resultClass="User">
SELECT * User
<dynamic prepend="WHERE ">
<isNull property="id">
id IS NULL
</isNull>
<isNotNull property="id">
id = #id#
</isNotNull>
</dynamic>
</select>
ibatis的动态标签分为一元条件元素标签和二元条件元素标签:
一元条件元素
<isPropertyAvailable>
检查是否存在该属性(存在parameter bean的属性)。
<isNotPropertyAvailable>
检查是否不存在该属性(不存在parameter bean的属性)。
<isNull>
检查属性是否为null。
<isNotNull>
检查属性是否不为null。
<isEmpty>
检查Collection.size()的值,属性的String或String.valueOf()值,是否为null或空(“”或size() < 1)。
<isNotEmpty>
检查Collection.size()的值,属性的String或String.valueOf()值,是否不为null或不为空(“”或size() > 0)。 例子:
<isNotEmpty prepend=”AND” property=”firstName” > FIRST_NAME=#firstName# </isNotEmpty>
二元条件元素
<isEqual>
比较属性值和静态值或另一个属性值是否相等。
<isNotEqual>
比较属性值和静态值或另一个属性值是否不相等。
<isGreaterThan>
比较属性值是否大于静态值或另一个属性值。
<isGreaterEqual>
比较属性值是否大于等于静态值或另一个属性值。
<isLessThan>
比较属性值是否小于静态值或另一个属性值。
<isLessEqual>
比较属性值是否小于等于静态值或另一个属性值。 例子: <isLessEqual prepend=”AND” property=”age” compareValue=”18”> ADOLESCENT = ‘TRUE’ </isLessEqual>
prepend - 可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
property - 被比较的属性(必选)
compareProperty - 另一个用于和前者比较的属性(必选或选择compareValue)
compareValue - 用于比较的值(必选或选择compareProperty)
还有两个其它的条件元素,<isParameterPresent>,<iterate>就不说了,用到的时候可以再查。
ibatis 动态标签的嵌套
说到动态标签,那就不得不说一下动态标签的嵌套查询了。在我进行项目开发的时候,由于存在一个查询报表的功能,该功能涉及到的数据库表特别多,所以查询条件非常复杂,这时候不得不要到动态标签的嵌套查询了。例如:
<dynamic>
<isEqual property="reimburseType" compareValue="1">
left join
(
select ReimbursementRevisionId
from f_reimbursement_type_travel
where 1=1
<isNotNull prepend="and" property="BusinessPersonName">
BusinessPersonName = #applicationType#
</isNotNull>
<isNotNull prepend="and" property="Position">
Position = #Position#
</isNotNull>
)as rtt
on rr.ReimbursementRevisionId = rtt.ReimbursementRevisionId
</isEqual>
</dynamic>
理论上来说,动态标签是可以任意嵌套的,比如<isEqual>里面可以嵌套<isEqual>;但是嵌套也有一些要求,比如,<dynamic>标签里面就不能嵌套<dynamic>标签,另外我还发现<isGreaterEqual>里嵌套<isLessEqual>不能实现预期的功能,比如我想在detailType属性在3-6,8-10时,执行查询语句,代码如下:
<isGreaterEqual property="detailType" compareValue="3">
<isLessEqual property="detailType" compareValue="10">
<isNotEqual property="detailType" compareValue="7">
join
(
select ProjectRevisionId,sum(DetailAmount) as DetailTotalAmount
from f_reimbursement_detail
group by ProjectRevisionId
where DetailTypeId = #detailType#
having 1=1
<isNotEmpty prepend="and" property="detailAmountMin">
DetailTotalAmount <![CDATA[>=]]> #detailAmountMin#
</isNotEmpty>
<isNotEmpty prepend="and" property="detailAmountMax">
DetailTotalAmount <![CDATA[<=]]> #detailAmountMax#
</isNotEmpty>
) as rf on rf.ProjectRevisionId = rr.ProjectRevisionId
</isNotEqual>
</isLessEqual>
</isGreaterEqual>
如果传参detailType=5,运行过后,发现程序在执行上面代码时sql语句中并没有以上的语句,但是如果只是下面这样写,则一点问题也没有,这让我很郁闷。
<isGreaterEqual property="detailType" compareValue="3">
join
(
select ProjectRevisionId,sum(DetailAmount) as DetailTotalAmount
from f_reimbursement_detail
group by ProjectRevisionId
where DetailTypeId = #detailType#
having 1=1
<isNotEmpty prepend="and" property="detailAmountMin">
DetailTotalAmount <![CDATA[>=]]> #detailAmountMin#
</isNotEmpty>
<isNotEmpty prepend="and" property="detailAmountMax">
DetailTotalAmount <![CDATA[<=]]> #detailAmountMax#
</isNotEmpty>
) as rf on rf.ProjectRevisionId = rr.ProjectRevisionId
</isGreaterEqual-->
ibatis使用过程中应该知道的知识:
1.占位符
#是占位符,$是字符串拼接。id = #id# 生成的sql语句是 id = ? 使用的是PreparedStatement,执行时,通过setXXX方法,将值加入到sql语句中。
若字段id为String类型,传递的参数id为1,
则 id = #id# 实际SQL为:select * from user where a = ‘1’;
而 id = $id$ 实际SQL为:select * from user where a = 1;
注:尽量用#id# 而不要用$id$ ,因为后面这种只是拼接,很容易被sql注入攻击。
2.动态生成查询的结果列:
有时会出现不能动态生成查询结果列的情况,那是因为ibaits 会缓存查询的meta信息,所以在生成动态列时一定要加上 remapResults="true"。
<select id="getxx" resultClass="java.util.HashMap" parameterClass="map" remapResults="true">
3.动态指定表名
有时会碰到2张表结构相同,但是表名不一样的情况,这时候查询语句中的表名就需要动态指定了。这时只能用$tableName$,而不能用#tableName#。
select * from $tableName$ where id = #id#
4.动态标签里面的属性
1)dynamic的prepend只要检测到第一个条件为“真”的比较元素,则覆盖其prepend属性并组装where关键字为动态SQL的一部分。 若果dynamic下面第一条动态标签不含prepend属性,则会覆盖第二个条件为“真”的动态标签的prepend属性值,所有最好每个动态标签都加上prepend属性。
2)isNotNull的prepend='and' 只要检测到参数值满足比较条件,则前置组装and关键字为动态SQL的一部分。
5.动态sql片段
//动态sql片段
<sql id="sql_count">
select count(*)
</sql>
<sql id="sql_select">
select *
</sql>
<sql id="sql_where">
from student
<dynamic prepend="where">
<isNotEmpty prepend="and" property="name">
name like '%$name$%'
</isNotEmpty>
<isNotEmpty prepend="and" property="no">
no like '%no$%'
</isNotEmpty>
</dynamic>
</sql>
<select id="findStudentCount" parameterClass="map" resultClass="int">
<include refid="sql_count"/>
<include refid="sql_where"/>
</select>
<select id="findStudent" parameterClass="map" resultMap="student.result_base">
<include refid="sql_select"/>
<include refid="sql_where"/>
ibatis 中动态SQL查询和动态标签嵌套的使用的更多相关文章
- MyBatis中的条件查询(动态sql)
本文将介绍使用MyBatis框架,编写DAO层接口类和接口类对应的sql映射文件,使用动态sql查询满足条件的用户集合. 首先,需要创建一个实体类User,供封装数据使用: package com.x ...
- MyBatis动态SQL之一使用 if 标签和 choose标签
bootstrap react https://segmentfault.com/a/1190000010383464 xml 中 < 转义 to thi tha <if test=&qu ...
- .NET在EF中使用sql,用动态类吧!
.NET在EF中使用sql,用动态类吧! 前言 在.NET中使用Entity Framework能快速.方便地结合LINQ来对数据库进行一系列的增删改查操作.但是由于EF根据表达式最后生成通用的sql ...
- SQL Server-聚焦深入理解动态SQL查询(三十二)
前言 之前有园友一直关注着我快点出SQL Server性能优化系列,博主我也对性能优化系列也有点小期待,本来打算利用周末写死锁以及避免死锁系列的接着进入SQL Server优化系列,但是在工作中长时间 ...
- SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?
前言 之前我们已经讨论过动态SQL查询呢?这里为何再来探讨一番呢?因为其中还是存在一定问题,如标题所言,很多面试题也好或者有些博客也好都在说在执行动态SQL查询时sp_executesql的性能比ex ...
- 64位环境中使用SQL查询excel的方式解决
--64位环境中使用SQL查询excel的方式 环境: OS:Windows Server 2008 R2 Enterprise MSSQL:Microsoft SQL Server 2008 R2 ...
- ignite中的sql查询
ignite中进行sql查询需要对要查询的cache和字段进行配置,可以在xml中配置,也可以在代码中配置或进行注解,我用的是xml配置: <!-- 配置cache --> <pro ...
- Mybatis中多个参数的问题&&动态SQL&&查询结果与类的对应
### 1. 抽象方法中多个参数的问题 在使用MyBatis时,接口中的抽象方法只允许有1个参数,如果有多个参数,例如: Integer updatePassword( Integer id, Str ...
- 一步步学Mybatis-怎么样实现动态SQL查询(6)
上一章我们已经讲完了关于Mybatis的分页用法,其实MyBatis 还具有的一个强大的特性之一通常是它的动态 SQL 能力. 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 S ...
随机推荐
- Git config文件
查看该文件: git config --global --list Ref: https://blog.csdn.net/themagickeyjianan/article/details/79683 ...
- Echarts的提示(Tooltip)显示额外内容
官方一般都是: 而我们通常是需要显示额外内容的,比如这样 其中Tooltip也是参考了网友的写法 option = { tooltip: { trigger: 'axis', formatter: f ...
- python 开机 定时启动
Windows开机自动运行.py文件1.找到写好的.py文件,例如我的.py文件路径:D:\编程测试文件\untitled\03131105.py 2.选中文件03131105.py,右键——属性—— ...
- 《学渣Linux笔记》——关于.bashrc与profile(涉及交互式与非交互式、登录与非登录shell)
<学渣Linux笔记>--关于.bashrc与profile(涉及交互式与非交互式.登录与非登录shell) 1.基本概念(个人理解) 交互式shell:等待用户输入,并执行相应操作的sh ...
- MySQL恩恩怨怨
数据库基础 Windows安装MySQL Mac安装MySQL Linux安装MySQL MySQL存储引擎概述 MySQL表操作 MySQL支持的数据类型 MySQL表的完整性约束 MySQL记录操 ...
- java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
请求的协议不对 解决方案: 把请求的https改成http
- ubuntu 安装和配置 GitLab
一.概述 GitLab 是一个基于 Web 的开源 Git 软件仓库管理器,用 Ruby 编写,包括 wiki,问题管理,代码审查,监控以及持续集成和部署.它使开发人员能够创建,审查和部署他们的项目. ...
- 从损失函数优化角度:讨论“线性回归(linear regression)”与”线性分类(linear classification)“的联系与区别
1. 主要观点 线性模型是线性回归和线性分类的基础 线性回归和线性分类模型的差异主要在于损失函数形式上,我们可以将其看做是线性模型在多维空间中“不同方向”和“不同位置”的两种表现形式 损失函数是一种优 ...
- 你也可以写个聊天程序 - C# Socket学习1
原文:你也可以写个聊天程序 - C# Socket学习1 简述 我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解.我今天就来和大家一起学习下Socket,并写一个简单 ...
- Linux生产环境上,最常用的一套“Sed“技巧
sed命令应用广泛,使用简单,是快速文本处理的利器.它其实没多少技巧,背诵.使用是最合适的学习渠道,属于硬技能.但它又很复杂,因为高级功能太多.本篇不去关注sed的高级功能,仅对常用的一些操作,进行说 ...