sqlmap.docx
《sqlmap.docx》由会员分享,可在线阅读,更多相关《sqlmap.docx(9页珍藏版)》请在冰豆网上搜索。
![sqlmap.docx](https://file1.bdocx.com/fileroot1/2022-11/25/a6458450-a509-4616-94e2-d27ea87fa7bd/a6458450-a509-4616-94e2-d27ea87fa7bd1.gif)
sqlmap
摘自IBatis官网java版中文开发文档,动态SQL,优雅的条件组合:
直接使用JDBC一个非常普遍的问题是动态SQL。
使用参数值、参数本身和数据列都是动态的SQL,通常非常困难。
典型的解决方法是,使用一系列if-else条件语句和一连串讨厌的字符串连接。
对于这个问题,SQL Map API使用和mapped statement非常相似的结构,提供了较为优雅的方法。
这里是一个简单的例子:
程序代码:
上面的例子中,根据参数bean“id”属性的不同情况,可创建两个可能的语句。
如果参数“id”大于0,将创建下面的语句:
程序代码:
select * from ACCOUNT where ACC_ID = ?
或者,如果“id”参数小于等于0,将创建下面的语句:
程序代码:
select * from ACCOUNT
在更复杂的例子中,动态Mapped Statement的用处更明显。
如下面比较复杂的例子:
程序代码:
select * from ACCOUNT
(ACC_FIRST_NAME = #firstName#
ACC_LAST_NAME = #lastName#
)
ACC_EMAIL like #emailAddress#
ACC_ID = #id#
order by ACC_LAST_NAME
Clinton Begin 著 刘涛(toleu@) 译
开发指南 iBATIS SQL Maps Page 42 of 62
根据不同的条件,上面动态的语句可以产生16条不同的查询语句。
使用if-else结构和字符串,会产生上百行很乱的代码。
而使用动态Statement,和在SQL的动态部位周围插入条件标签一样容易。
例如:
程序代码:
select * from ACCOUNT
ACC_ID = #id#
ACC_LAST_NAME = #lastName#
order by ACC_LAST_NAME
上面的例子中,元素划分出SQL语句的动态部分。
动态部分可以包含任意多的条件标签元素,条件标签决定是否在语句中包含其中的SQL代码。
所有的条件标签元素将根据传给动态查询Statement的参数对象的情况来工作。
元素和条件元素都有“prepend”属性,它是动态SQL代码的一部分,在必要情况下,可以被父元素的“prepend”属性覆盖。
上面的例子中,prepend属性“where”将覆盖第一个为“真”的条件元素。
这对于确保生成正确的SQL语句是有必要的。
例如,在第一个为“真”的条件元素中,“AND”是不需要的,事实上,加上它肯定会出错(ibatis还是挺周到的,-_-,得试验下如果为“假”的情况,这个"WHERE”还在不在了)。
以下小节讨论不同的条件元素,包括二元条件元素,一元条件元素和其他动态元素。
//==========================================
摘自 javaeye
在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的并不只是SQL 中的参数,包括Select 语句中所包括的字段和限定条件,都可能发生变化。
典型情况,如在一个复杂的组合查询页面,我们必须根据用户的选择和输入决定查询的条件组合。
一个典型的页面如下:
对于这个组合查询页面,根据用户选择填写的内容,我们应为其生成不同的查询语句。
如用户没有填写任何信息即提交查询请求,我们应该返回所有记录:
Select * from t_user;
如用户只在页面上填写了姓名“Erica”,我们应该生成类似:
Select * from t_user where name like ‘%Erica%’ ;的SQL查询语句。
如用户只在页面上填写了地址“Beijing”,我们应该生成类似:
Select * from t_user where address like ‘%Beijing%”;的SQL。
而如果用户同时填写了姓名和地址(”Erica”&’Beijing’),则我们应生成类似:
Select * from t_user where name like ‘%Erica%’ and address like ‘%Beijing%”的SQL查询语句。
对于ibatis 这样需要预先指定SQL 语句的ORM 实现而言,传统的做法无非通过if-else 语句对输入参数加以判定,然后针对用户选择调用不同的statement 定义。
对于上面这种简单的情况(两种查询条件的排列组合,共4 种情况)而言,statement 的重复定义工作已经让人不厌其烦,而对于动辄拥有七八个查询条件,乃至十几个查询条件
的排列组合而言,琐碎反复的statement定义实在让人不堪承受。
考虑到这个问题,ibatis引入了动态映射机制,即在statement定义中,根据不同的
查询参数,设定对应的SQL语句。
还是以上面的示例为例:
通过dynamic 节点,我们定义了一个动态的WHERE 子句。
此WHERE 子句中将
可能包含两个针对name 和address 字段的判断条件。
而这两个字段是否加入检索取决于用户所提供的查询条件(字段是否为空[isNotEmpty])。
对于一个典型的Web程序而言,我们通过HttpServletRequest获得表单中的字段名并将其设入查询参数,如:
user.setName(request.getParameter("name"));
user.setAddress(request.getParameter("address"));
sqlMap.queryForList("User.getUsers", user);
在执行queryForList("User.getUsers", user)时,ibatis 即根据配置文
件中设定的SQL动态生成规则,创建相应的SQL语句。
上面的示例中,我们通过判定节点isNotEmpty,指定了关于name 和address 属
性的动态规则:
(name like #name#)
这个节点对应的语义是,如果参数类的"name"属性非空(isNotEmpty,即非空
字符串””),则在生成的SQL Where字句中包括判定条件(name like #name#),其
中#name#将以参数类的name属性值填充。
Address属性的判定生成与name属性完全相同,这里就不再赘述。
这样,我们通过在statement 定义中引入dynamic 节点,很简单的实现了SQL 判定子句的动态生成,对于复杂的组合查询而言,这将带来极大的便利。
判定节点的定义可以非常灵活,我们甚至可以使用嵌套的判定节点来实现复杂的动态映射,如:
( name=#name#
address=#address#
)
这段定义规定,只有用户提供了姓名信息时,才能结合地址数据进行查询(如果只提供地址数据,而将姓名信息忽略,将依然被视为全检索)。
Dynamic节点和判定节点中的prepend属性,指明了本节点中定义的SQL子句在
主体SQL中出现时的前缀。
如:
(name like #name#)
(address like #address#)
假设"name"属性的值为“Erica”, "address"属性的值为“Beijing”,则会生成类似下面的SQL子句(实际运行期将生成带占位符的PreparedStatement,之后再为其填充数据):
WHERE (name like ‘Beijing’) AND (address like ‘Beijing’)
其中WHERE 之后的语句是在dynamic 节点中所定义,因此以dynamic 节点的prepend设置("WHERE")作为前缀,而其中的”AND”,实际上是address属性所对应的isNotEmpty节点的prepend设定,它引领了对应节点中定义的SQL子句。
至于name属性对应的isNotEmpty节点,由于ibatis会自动判定是否需要追加prepend前缀,这里(name like #name#)是WHERE 子句中的第一个条件子句,无需AND 前缀,所以自动省略。
判定节点并非仅限于isNotEmpty,ibatis中提供了丰富的判定定义功能。
判定节点分两类:
一元判定
一元判定是针对属性值本身的判定,如属性是否为NULL,是否为空值等。
上面示例中isNotEmpty就是典型的一元判定。
一元判定节点有:
节点名 描述
参数类中是否提供了此属性
与相反
属性值是否为NULL
与相反
如果属性为Collection或者String,其size是否<1,如果非以上两种类型,则通过String.valueOf(属性值)
获得其String类型的值后,判断其size是否<1 与相反。
二元判定
二元判定有两个判定参数,一是属性名,而是判定值,如
compareValue="18">
(age=#age#)
其中,property="age"指定了属性名”age”,compareValue=”18”指明了判定值为”18”。
上面判定节点isGreaterThan 对应的语义是:
如果age 属性大于18(compareValue),则在SQL中加入(age=#age#)条件。
二元判定节点有:
节点名 属性值与compareValues的关系
相等。
不等。
大于
大于等于
小于
小于等于
ibatis动态mappedStatement配置详解
分类:
Database2007-08-2311:
10 2862人阅读 评论
(1) 收藏 举报
动态MappedStatement
直接使用JDBC一个非常普遍的问题是动态SQL。
使用参数值、参数本身和数据列都
是动态的SQL,通常非常困难。
典型的解决方法是,使用一系列if-else条件语句和一连串
讨厌的字符串连接。
对于这个问题,SQLMapAPI使用和mappedstatement非常相似的结构,
提供了较为优雅的方法。
这里是一个简单的例子:
cacheModel="account-cache"
resultMap="account-result">
select*fromACCOUNT
whereACC_ID=#id#
orderbyACC_LAST_NAME
上面的例子中,根据参数bean“id”属性的不同情况,可创建两个可能的语句。
如果参
数“id”大于0,将创建下面的语句:
select*fromACCOUNTwhereACC_ID=?
或者,如果“id”参数小于等于0,将创建下面的语句:
select*fromACCOUNT
在更复杂的例子中,动态MappedStatement的用处更明显。
如下面比较复杂的例子:
select*fromACCOUNT
(ACC_FIRST_NAME=#firstName#
ACC_LAST_NAME=#lastName#
)
ACC_EMAILlike#emailAddress#
ACC_ID=#id#
orderbyACC_LAST_NAME
根据不同的条件,上面动态的语句可以产生16条不同的查询语句。
使用if-else结构和
字符串,会产生上百行很乱的代码。
而使用动态Statement,和在SQL的动态部位周围插入条件标签一样容易。
例如:
select*fromACCOUNT
ACC_ID=#id#
ACC_LAST_NAME=#lastName#
orderbyACC_LAST_NAME
上面的例子中,元素划分出SQL语句的动态部分。
动态部分可以包含任意多
的条件标签元素,条件标签决定是否在语句中包含其中的SQL代码。
所有的条件标签元素
将根据传给动态查询Statement的参数对象的情况来工作。
元素和条件元素都有
“prepend”属性,它是动态SQL代码的一部分,在必要情况下,可以被父元素的“prepend”
属性覆盖。
上面的例子中,prepend属性“where”将覆盖第一个为“真”的条件元素。
这对
于确保生成正确的SQL语句是有必要的。
例如,在第一个为“真”的条件元素中,“AND”
是不需要的,事实上,加上它肯定会出错。
以下小节讨论不同的条件元素,包括二元条件元
素,一元条件元素和其他动态元素。
二元条件元素
二元条件元素将一个属性值和一个静态值或另一个属性值比较,如果条件为“真”,元
素体的内容将被包括在查询SQL语句中。
二元条件元素的属性:
prepend -可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
property -被比较的属性(必选)
compareProperty - 另一个用于和前者比较的属性(必选或选择compareValue)
compareValue - 用于比较的值(必选或选择compareProperty)
比较属性值和静态值或另一个属性值是否相等。
比较属性值和静态值或另一个属性值是否不相等。
比较属性值是否大于静态值或另一个属性值。
比较属性值是否大于等于静态值或另一个属性值。
比较属性值是否小于静态值或另一个属性值。
比较属性值是否小于等于静态值或另一个属性值。
例子:
ADOLESCENT=‘TRUE’
一元条件元素
一元条件元素检查属性的状态是否符合特定的条件。
一元条件元素的属性:
prepend -可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
property -被比较的属性(必选)
检查是否存在该属性(存在parameterbean的属性)。
检查是否不存在该属性(不存在parameterbean的属性)。
检查属性是否为null。
检查属性是否不为null。
检查Collection.size()的值,属性的String或String.valueOf()值,
是否为null或空(“”或size()<1)。
检查Collection.size()的值,属性的String或String.valueOf()值,
是否不为null或不为空(“”或size()>0)。
例子:
FIRST_NAME=#firstName#
其他元素 ParameterPresent:
这些元素检查参数对象是否存在。
ParameterPresent的属性:
prepend -可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
检查是否存在参数对象(不为null)。
检查是否不存在参数对象(参数对象为null)。
例子:
EMPLOYEE_TYPE=‘DEFAULT’
Iterate:
这属性遍历整个集合,并为List集合中的元素重复元素体的内容。
Iterate的属性:
prepend -可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
property -类型为java.util.List的用于遍历的元素(必选)
open - 整个遍历内容体开始的字符串,用于定义括号(可选)
close -整个遍历内容体结束的字符串,用于定义括号(可选)
conjunction- 每次遍历内容之间的字符串,用于定义AND或OR(可选)
遍历类型为java.util.List的元素。
例子: