- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章基于mybatis 动态SQL查询总结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
××项目需要提供系统部分函数第三方调用接口,基于安全性和避免暴露数据库表信息的基础上进行函数接口的设计,根据第三方调用身份的权限提供某张表的自定义集合.
本项目基于mybatis的持久层框架,支持定制化的SQL,这样可以避免拼接sql语句的痛苦.
例如拼接时要确保不能添加空格,还要注意去掉列表的最后一个列名的都逗号.
基于OGNL的表达式的mybatis框架可以彻底解决这种痛苦.
1
2
3
4
5
6
7
8
9
10
|
<
select
id=
"queryColumns"
resultType=
"map"
parameterType=
"java.util.HashMap"
>
select
column_name columnName, data_type dataType, column_comment columnComment
from
information_schema.columns
where
table_name = #{tablename}
and
column_name
in
<foreach collection=
"columnsArray"
item=
"column_name"
index
=
"index"
open
=
"("
close
=
")"
separator=
","
>
#{column_name}
</foreach>
</
select
>
|
1
2
3
4
5
6
7
|
<
select
id=
"query1"
resultType=
"map"
parameterType=
"java.util.HashMap"
>
select
<foreach collection=
"columnsArray"
item=
"item"
index
=
"index"
open
=
" "
separator=
", "
close
=
" "
>
${item}
</foreach>
from
#{tableName} tn
</
select
>
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<
select
id=
"query2"
resultType=
"map"
parameterType=
"java.util.HashMap"
>
select
<foreach collection=
"columnsArray"
item=
"item"
index
=
"index"
open
=
""
separator=
","
close
=
""
>
${item}
</foreach>
from
#{tableName} db
where
<if test =
"name !=null"
>
db.
name
=#{
name
}
and
</if>
db.LastModifyTime
between
#{datestart,jdbcType=
TIMESTAMP
}
and
#{dateend,jdbcType=
TIMESTAMP
}
</
select
>
|
Mybatis 的Mapper.xml语句中parameterType向SQL语句传参有两种方式:#{}和${} 。
我们经常使用的是#{},一般解说是因为这种方式可以防止SQL注入,简单的说#{}这种方式SQL语句是经过预编译的,它是把#{}中间的参数转义成字符串,举个例子:
1
|
select
*
from
student
where
studentName = #{
name
}
|
预编译后,会动态解析成一个参数标记符?:
1
|
select
*
from
student
where
studentName = ?
|
而使用${}在动态解析时候,会传入参数字符串 。
1
|
select
*
from
student
where
studentName =
'lyrics'
|
-看完上面的一些例子,可以看到主要用到了if 、foreach等元素,mybatis之前的版本,有很多的元素需要了解,而mybatis大大精简了元素种类,现在只需要学习以下几个元素:
-if 。
-choose(when,otherwise) 。
-trim(where,set) 。
-foreach 。
-- 引用[http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html] 。
if 。
动态SQL通常要做的是根据条件包含where子句的一部分。比如:
1
2
3
4
5
6
7
|
<
select
id=
"findActiveBlogWithTitleLike"
resultType=
"Blog"
>
SELECT
*
FROM
BLOG
WHERE
state = ‘ACTIVE'
<if test=
"title != null"
>
AND
title
like
#{title}
</if>
</
select
>
|
这条语句提供了一种可选的查找文本功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会对“title”一列进行模糊查找并返回 BLOG 结果(细心的读者可能会发现,“title”参数值是可以包含一些掩码或通配符的).
如果希望通过“title”和“author”两个参数进行可选搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可.
1
2
3
4
5
6
7
8
9
|
<
select
id=
"findActiveBlogLike"
resultType=
"Blog"
>
SELECT
*
FROM
BLOG
WHERE
state = ‘ACTIVE'
<if test=
"title != null"
>
AND
title
like
#{title}
</if>
<if test=
"author != null and author.name != null"
>
AND
author_name
like
#{author.
name
}
</if>
</
select
>
|
choose,when,otherwise 。
有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句.
还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找的情形,若两者都没有提供,就返回所有符合条件的 BLOG(实际情况可能是由管理员按一定策略选出 BLOG 列表,而不是返回大量无意义的随机结果).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
select
id=
"findActiveBlogLike"
resultType=
"Blog"
>
SELECT
*
FROM
BLOG
WHERE
state = ‘ACTIVE'
<choose>
<
when
test=
"title != null"
>
AND
title
like
#{title}
</
when
>
<
when
test=
"author != null and author.name != null"
>
AND
author_name
like
#{author.
name
}
</
when
>
<otherwise>
AND
featured = 1
</otherwise>
</choose>
</
select
>
|
trim, where, set 。
前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在回到“if”示例,这次我们将“ACTIVE = 1”也设置成动态的条件,看看会发生什么.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<
select
id=
"findActiveBlogLike"
resultType=
"Blog"
>
SELECT
*
FROM
BLOG
WHERE
<if test=
"state != null"
>
state = #{state}
</if>
<if test=
"title != null"
>
AND
title
like
#{title}
</if>
<if test=
"author != null and author.name != null"
>
AND
author_name
like
#{author.
name
}
</if>
</
select
>
|
如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:
1
2
|
SELECT
*
FROM
BLOG
WHERE
|
这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样
1
2
3
|
SELECT
*
FROM
BLOG
WHERE
AND
title
like
‘someTitle'
|
这个查询也会失败。这个问题不能简单地用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不会再写出这种语句了.
MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
select
id=
"findActiveBlogLike"
resultType=
"Blog"
>
SELECT
*
FROM
BLOG
<
where
>
<if test=
"state != null"
>
state = #{state}
</if>
<if test=
"title != null"
>
AND
title
like
#{title}
</if>
<if test=
"author != null and author.name != null"
>
AND
author_name
like
#{author.
name
}
</if>
</
where
>
</
select
>
|
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除.
如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
1
2
3
|
<trim prefix=
"WHERE"
prefixOverrides=
"AND |OR "
>
...
</trim>
|
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容.
类似的用于动态更新语句的解决方案叫做 set。set 元素可以用于动态包含需要更新的列,而舍去其它的。比如:
1
2
3
4
5
6
7
8
9
10
|
<
update
id=
"updateAuthorIfNecessary"
>
update
Author
<
set
>
<if test=
"username != null"
>username=#{username},</if>
<if test=
"password != null"
>
password
=#{
password
},</if>
<if test=
"email != null"
>email=#{email},</if>
<if test=
"bio != null"
>bio=#{bio}</if>
</
set
>
where
id=#{id}
</
update
>
|
这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留) 。
若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:
1
2
3
|
<trim prefix=
"SET"
suffixOverrides=
","
>
...
</trim>
|
注意这里我们删去的是后缀值,同时添加了前缀值.
foreach 。
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
1
2
3
4
5
6
7
8
9
|
<
select
id=
"selectPostIn"
resultType=
"domain.blog.Post"
>
SELECT
*
FROM
POST P
WHERE
ID
in
<foreach item=
"item"
index
=
"index"
collection=
"list"
open
=
"("
separator=
","
close
=
")"
>
#{item}
</foreach>
</
select
>
|
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符.
-释义:
-collection :collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、array、map,上面传的参数为数组,所以值为array 。
-item : 表示在迭代过程中每一个元素的别名 。
-index :表示在迭代过程中每次迭代到的位置(下标) 。
-open :前缀 。
-close :后缀 。
-separator :分隔符,表示迭代时每个元素之间以什么分隔 。
我们通常可以将之用到批量删除、添加等操作中.
你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数.
当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素.
当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://www.cnblogs.com/jc1997/p/10915286.html 。
最后此篇关于基于mybatis 动态SQL查询总结的文章就讲到这里了,如果你想了解更多关于基于mybatis 动态SQL查询总结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
SQL、PL-SQL 和 T-SQL 之间有什么区别? 谁能解释一下这三者之间的区别,并提供每一个的相关使用场景? 最佳答案 SQL 是一种对集合进行操作的查询语言。 它或多或少是标准化的,几乎所有关
这个问题已经有答案了: What is the difference between SQL, PL-SQL and T-SQL? (6 个回答) 已关闭 9 年前。 我对 SQL 的了解足以完成我的
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列有一个默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任
我有一个可能属于以下类型的字符串 string expected result 15-th-rp 15 15/12-rp 12 15-12-th
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 9年前关闭
我有一个存储过程(称为 sprocGetArticles),它从文章表中返回文章列表。这个存储过程没有任何参数。 用户可以对每篇文章发表评论,我将这些评论存储在由文章 ID 链接的评论表中。 有什么方
我目前正在做一个 *cough*Oracle*cough* 数据库主题。讲师介绍embedded SQL作为让其他语言(例如 C、C++)与(Oracle)数据库交互的方式。 我自己做了一些数据库工作
SQL Server 中 SQL 语句的最大长度是多少?这个长度是否取决于 SQL Server 的版本? 例如,在 DECLARE @SQLStatement NVARCHAR(MAX) = N'S
这个问题已经有答案了: Simple way to transpose columns and rows in SQL? (9 个回答) 已关闭 8 年前。 CallType
预先感谢您对此提供的任何帮助。 假设我有一个查询,可以比较跨年的数据,从某个任意年份开始,永无止境(进入 future ),每年同一时期直到最后一个完整的月份(其特点是一月数据永远不会显示至 2 月
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列的默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任何数
下面是我试图用来检查存储过程是否不存在然后创建过程的 sql。它会抛出一个错误:Incorrect syntax near the keyword 'PROCEDURE' IF NOT EXISTS
我有一个同事声称动态 SQL 在许多情况下比静态 SQL 执行得更快,所以我经常看到 DSQL 到处都是。除了明显的缺点,比如在运行之前无法检测到错误并且更难阅读,这是否准确?当我问他为什么一直使用
来自 lobodava 的动态 SQL 查询是: declare @sql nvarchar(4000) = N';with cteColumnts (ORDINAL_POSITION, CO
使用 SQL Server 中的存储过程执行动态 SQL 命令的现实优点和缺点是什么 EXEC (@SQL) 对比 EXEC SP_EXECUTESQL @SQL ? 最佳答案 sp_executes
我有这个有效的 SQL 查询: select sum(dbos.Points) as Points, dboseasons.Year from dbo.StatLines dbos i
我正在调试一些构建成功运行的 SQL 命令的代码。 然而,在查询结束时,查询结果似乎被写入了一个文本文件。 完整的查询如下 echo SELECT DATE,DATETABLE,DATE,APPDAT
我有一些创建表的 .sql 文件(MS SQL 数据库): 表_1.sql: IF OBJECT_ID (N'my_schema.table1', N'U') IS NOT NULL DROP TAB
我写了下面的 SQL 存储过程,它一直给我错误@pid = SELECT MAX(... 整个过程是: Alter PROCEDURE insert_partyco @pname varchar(20
我在 SQL Server 2005 中有包含两列 Fruit 和 Color 的表,如下所示 Fruit Colour Apple Red Orange
我是一名优秀的程序员,十分优秀!