1.为什么需要动态 SQL
1 、动态 SQL 是 MyBatis 的强大特性之一
2 、使用 JDBC 或其它类似的框架,根据不同条件拼接 SQL 语句非常麻烦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号等
3 、 SQL 映射语句中的强大的动态 SQL 语言 , 可以很好的解决这个问题 .
2.动态 SQL- 基本介绍
● 基本介绍
-
在一个实际的项目中, sql 语句往往是比较复杂的
-
为了满足更加复杂的业务需求, MyBatis 的设计者,提供了动态生成 SQL 的功能。
● 动态 SQL 必要性
-
比如我们查询 Monster 时,如果程序员输入的 age 不大于 0, 我们的 sql 语句就不带 age 。
-
更新 Monster 对象时,没有设置的新的属性值,就保持原来的值,设置了新的值,才更
2.解决方案: MyBatis 提供的动态SQL 机制
● 动态 SQL 常用标签
动态 SQL 提供了如下几种常用的标签,类似我们 Java 的控制语句:
-
if [ 判断 ]
-
where [ 拼接 where 子句 ]
-
choose/when/otherwise [ 类似 java 的 switch 语句 , 注意是单分支 ]
-
foreach [ 类似 in ]
-
trim [ 替换关键字 / 定制元素的功能 ]
-
set [ 在 update 的 set 中,可以保证进入 set 标签的属性被修改,而没有进入 set 的,保
持原来的值 ]
3.动态 SQL- 案例演示
● 需求:请查询 age 大于 10 的所有妖怪,如果程序员输入的 age 不大于 0, 则输出所有
的妖怪
//根据age查询结果
public List findMonsterByAge(@Param(value = "age") Integer age);
SELECT * FROM monster
WHERE 1 = 1
AND age > #{age}
public void findMonsterByAge() {
List monsters =
monsterMapper.findMonsterByAge(10);
for (Monster monster : monsters) {
System.out.println("monster--" + monster);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("操作成功~");
}
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”, where 元素也会将它们去除(去掉多余的”AND” 或 “OR)。
● where 标签应用实例
需求:查询 id 大于 20 的,并且名字是 ” 牛魔王 ” 的所有妖怪 , 注意,如果名字为空,
或者输入的 id 小于 0, 则不拼接 sql 语句 ( 梳理:如果名字为空 , 就不带名字条件 ,
如果输入的 id 小于 0, 就不带 id 的条件 )
● 需求:如果给的 name 不为空,就按名字查询妖怪,如果指定的 id>0 ,就按 id 来查询妖
怪, 要求使用 choose/when/otherwise 标签实现 , 传入参数要求使用 Map
//测试choose标签的使用
public List findMonsterByIdOrName_choose(Map map);
SELECT * FROM monster
WHERE name
= #{name}
WHERE id
> #{id}
WHERE salary
> 100
public void findMonsterByIdOrName_choose() {
Map map = new HashMap<>();
//map.put("name", "牛魔王-100");
map.put("id", -1);
List monsters = monsterMapper.findMonsterByIdOrName_choose(map);
for (Monster monster : monsters) {
System.out.println("monster--" + monster);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("操作成功~");
}
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 :你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach 。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
●需求:查询monster_id 为20, 22, 34 的妖怪
//测试foreach的标签使用
public List findMonsterById_forEach(Map map);
SELECT * FROM monster
id IN
#{id}
public void findMonsterById_forEach() {
Map map = new HashMap<>();
map.put("ids", Arrays.asList(10, 12, 14));
List monsters =
monsterMapper.findMonsterById_forEach(map);
for (Monster monster : monsters) {
System.out.println("monster--" + monster);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("操作成功~");
}
● trim 可以替换一些关键字 .
要求:按名字和年龄查询妖怪,如果 sql 语句有 and | or 就替换成 where
//trim标签的使用
public List findMonsterByName_Trim(Map map);
SELECT * FROM monster
AND name
= #{name}
AND age
> #{age}
set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
●需求:请对指定id 的妖怪进行 修改,如果没有设置新的属性,则保持原来的值
//测试Set标签
public void updateMonster_set(Map map);
UPDATE monster
age
= #{age} ,
email
= #{email} ,
name
= #{name} ,
birthday
= #{birthday} ,
salary
= #{salary} ,
gender
= #{gender} ,
WHERE id = #{id}
public void updateMonster_set() {
Map map = new HashMap<>();
map.put("id", 3);
map.put("name", "牛魔王5-100");
monsterMapper.updateMonster_set(map);
//修改需要有commit
if (sqlSession != null) {
sqlSession.commit();
sqlSession.close();
}
System.out.println("操作成功~");
}
像这个例子我们就可以看出来set是利用if的判断,如果我们在测试文件中没有改变,那么就是空,这个时候就会还是原来的值,相反当我们进行改变的时候,不为空,那么相应的字段的值就会发生改变——>这个例子就是把name字段进行了改变,其他的字段没有发生变化
Original: https://blog.csdn.net/weixin_54107527/article/details/127807304
Author: 海绵hong
Title: MyBatis中动态 SQL 语句-更复杂的查询业务需求
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/653617/
转载文章受原作者版权保护。转载请注明原作者出处!