文章目录:
1.什么是动态SQL?
动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接SQL 语句。这里的条件判断使用的表达式为 OGNL 表达式。常用的动态 SQL标签有<if>、<where>、<foreach>、<sql>等。
MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似。
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的SQL 语句。此时,可使用动态 SQL 来解决这样的问题。
使用动态SQL时,dao接口中方法的形参要使用Java对象。
2.MyBatis中的动态SQL
2.1 动态SQL——if标签
2.1.1 语法格式
-
<if test="boolean判断结果">
<!--要么为true、要么为false-->
-
sql语句的部分
-
</if>
-
<!-- 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段断拼接到其所在的 SQL 语句中。 -->
2.1.2 应用举例
-
package com.bjpowernode.dao;
-
-
-
import com.bjpowernode.entity.Student;
-
-
import java.util.List;
-
-
/**
-
*
-
*/
-
public
interface
StudentDao {
-
-
//if
-
List<Student>
selectIf
(Student student);
-
-
}
-
<!-- if
-
test: 使用对象的属性值作为条件
-
-->
-
<select id="selectIf" resultType="com.bjpowernode.entity.Student">
-
select *
-
from student
-
where id=-1
-
<if test="name!=null and name!=''">
-
or name=#{name}
-
</if>
-
-
<if test="age>0">
-
or age=#{age}
-
</if>
-
</select>
-
<!--
-
<if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 id=-1的子句。
-
因为,若 where 后的所有<if/>条件均为 false,而 where 后若又没有 id=-1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。
-
所以,在where 后,需要添加子句 id=-1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
-
-->
-
@Test
-
public
void
testSelectIf
() {
-
SqlSession
session
= MyBatisUtil.getSqlSession();
-
StudentDao studentDao=session.getMapper(StudentDao.class);
-
Student student=
new
Student();
-
student.setName(
"张起灵");
-
student.setAge(
20);
-
List<Student> students=studentDao.selectIf(student);
-
students.forEach( stu -> System.out.println(
"stu === " + stu) );
-
session.close();
-
}
根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇
-
select
*
-
from student
-
where id
=
-1
or name
="张起灵"
or age
=
20
2.2 动态SQL——where标签
2.2.1 语法格式
-
<where>
-
其他动态sql
-
</where>
2.2.2 应用举例
-
package com.bjpowernode.dao;
-
-
import com.bjpowernode.entity.Student;
-
-
import java.util.List;
-
-
/**
-
*
-
*/
-
public
interface
StudentDao {
-
-
//where
-
List<Student>
selectWhere
(Student student);
-
-
}
-
<!-- where -->
-
<select id="selectWhere" resultType="com.bjpowernode.entity.Student">
-
select *
-
from student
-
<where>
-
<if test="name!=null and name!=''">
-
or name=#{name}
-
</if>
-
-
<if test="age>0">
-
or age=#{age}
-
</if>
-
</where>
-
</select>
-
-
<!--
-
使用<where/>标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。
-
需要注意的是,第一个<if/>标签中的SQL 片断,可以不包含 and。不过,写上 and 也不错,where标签会将离它最近的 and 或者 or 删掉。
-
但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
-
-->
-
@Test
-
public
void
testSelectWhere
() {
-
SqlSession
session
= MyBatisUtil.getSqlSession();
-
StudentDao studentDao=session.getMapper(StudentDao.class);
-
Student student=
new
Student();
-
student.setName(
"张起灵");
-
student.setAge(
20);
-
List<Student> students=studentDao.selectWhere(student);
-
students.forEach( stu -> System.out.println(
"stu === " + stu) );
-
session.close();
-
}
根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇
-
select
*
-
from student
-
where id
=
-1
or name
="张起灵"
or age
=
20
2.3 动态SQL——foreach标签
2.3.1 语法格式
-
<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
-
#{item的值}
-
</foreach>
-
-
<!--
-
如果dao接口中方法的形参是数组,则collection="array"
-
如果dao接口中方法的形参是List,则collection="list"
-
#item的值}:获取集合成员的值
-
-->
2.3.2 应用举例1(简单类型)
-
package com.bjpowernode.dao;
-
-
import com.bjpowernode.entity.Student;
-
-
import java.util.List;
-
-
/**
-
*
-
*/
-
public
interface
StudentDao {
-
-
//for-each 1
-
List<Student>
selectForeachOne
(List<Integer> idlist);
-
-
}
-
<!-- foreach第一种方式,循环简单类型的List: List<Integer> -->
-
<select id="selectForeachOne" resultType="com.bjpowernode.entity.Student">
-
select *
-
from student
-
<if test="list!=null and list.size>0">
-
where id in
-
<foreach collection="list" open="(" close=")" separator="," item="stuid">
-
#{stuid}
-
</foreach>
-
</if>
-
</select>
-
@Test
-
public
void
testSelectForeachOne
() {
-
SqlSession
session
= MyBatisUtil.getSqlSession();
-
StudentDao studentDao=session.getMapper(StudentDao.class);
-
List<Integer> idlist=
new
ArrayList<>();
-
idlist.add(
1001);
-
idlist.add(
1002);
-
idlist.add(
1003);
-
List<Student> students=studentDao.selectForeachOne(idlist);
-
students.forEach( stu -> System.out.println(
"stu === " + stu));
-
session.close();
-
}
根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇
-
select
*
-
from student
-
where id
in (
1001,
1002,
1003)
2.3.2 应用举例2(对象类型)
-
package com.bjpowernode.dao;
-
-
import com.bjpowernode.entity.Student;
-
-
import java.util.List;
-
-
/**
-
*
-
*/
-
public
interface
StudentDao {
-
-
//for-each 2
-
List<Student>
selectForeachTwo
(List<Student> studentList);
-
-
}
-
<!-- foreach第二种方式,循环对象类型的List: List<Student> -->
-
<select id="selectForeachTwo" resultType="com.bjpowernode.entity.Student">
-
select *
-
from student
-
<if test="list!=null and list.size>0">
-
where id in
-
<foreach collection="list" open="(" close=")" separator="," item="stu">
-
#{stu.id}
-
</foreach>
-
</if>
-
</select>
-
@Test
-
public
void
testSelectForeachTwo
() {
-
SqlSession
session
= MyBatisUtil.getSqlSession();
-
StudentDao studentDao=session.getMapper(StudentDao.class);
-
List<Student> list=
new
ArrayList<>();
-
Student s1=
new
Student();
-
s1.setId(
1001);
-
Student s2=
new
Student();
-
s2.setId(
1002);
-
Student s3=
new
Student();
-
s3.setId(
1003);
-
list.add(s1);
-
list.add(s2);
-
list.add(s3);
-
List<Student> students=studentDao.selectForeachTwo(list);
-
students.forEach( stu-> System.out.println(
"stu === " + stu));
-
session.close();
-
}
根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇
-
select
*
-
from student
-
where id
in (
1001,
1002,
1003)
2.4 动态SQL——sql标签
2.4.1 语法格式
-
<sql id="...">
-
sql语句
-
</sql>
-
-
<include refid="sql标签的id属性值">
</include>
-
-
<!--
-
<sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。
-
而其它标签使用该 SQL 片断,需要使用<include/>子标签。
-
该<sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL 的任何位置。
-
-->
2.4.2 应用举例
-
package com.bjpowernode.dao;
-
-
import com.bjpowernode.entity.Student;
-
-
import java.util.List;
-
-
/**
-
*
-
*/
-
public
interface
StudentDao {
-
-
//代码片段
-
List<Student>
selectSql
(List<Student> studentList);
-
}
-
<!-- 定义代码片段 -->
-
<sql id="selectStudent">
-
select id,name,age from student
-
</sql>
-
<sql id="studentFieldList">
-
where id in
-
</sql>
-
<select id="selectSql" resultType="com.bjpowernode.entity.Student">
-
<include refid="selectStudent">
</include>
-
<if test="list!=null and list.size>0">
-
<include refid="studentFieldList">
</include>
-
<foreach collection="list" open="(" close=")" separator="," item="student">
-
#{student.id}
-
</foreach>
-
</if>
-
</select>
-
@Test
-
public
void
testSelectSql
() {
-
SqlSession
session
= MyBatisUtil.getSqlSession();
-
StudentDao studentDao=session.getMapper(StudentDao.class);
-
List<Student> list=
new
ArrayList<>();
-
Student s1=
new
Student();
-
s1.setId(
1001);
-
Student s2=
new
Student();
-
s2.setId(
1002);
-
Student s3=
new
Student();
-
s3.setId(
1003);
-
list.add(s1);
-
list.add(s2);
-
list.add(s3);
-
List<Student> students=studentDao.selectSql(list);
-
students.forEach( stu-> System.out.println(
"stu === " + stu));
-
session.close();
-
}
根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇
-
select id,name,age
-
from student
-
where id
in (
1001,
1002,
1003)