MyBatis
框架动态
SQL
动态 SQL-if
动态 SQL-where
动态 SQL-foreach
动态 SQL-片段
动态
SQL
,通过
MyBatis
提供的各种标签对条件作出判断以实现动态拼接
SQL
语句。这里的条件判
断使用的表达式为
OGNL
表达式。常用的动态
SQL
标签有
<if>
、
<where>
、
<foreach>
等。
动态
SQL
,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行
查询。提交的查询条件不同,执行的
SQL
语句不同。若将每种可能的情况均逐一列出,对所有条件进行
排列组合,将会出现大量的
SQL
语句。此时,可使用动态
SQL
来解决这样的问题。
1)动态 SQL 之<if>(对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。
语法:
<if test=”
条件
”> sql
语句的部分
</if>
)
接口方法:
//动态sql要使用java对象作为参数(if)
List<Student> selectStudentIf(Student student);
mapper
文件:
<!--if
<if test="使用参数java对象的属性值作为判断条件,语法 属性=xxx值">
-->
<select id="selectStudentIf" resultType="com.zsz.domain.Student">
<include refid="studentSql"></include>
where 1=1
<if test="name != null and name !=''">
and name =#{name}
</if>
<if test="age > 0">
or age >#{age}
</if>
</select>
测试方法:
@Test
public void testSelectStudentIf(){
SqlSession sqlSession= MybatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student student =new Student();
// student.setName("赵六");
// student.setAge(12);
student.setName("赵六");
student.setAge(18);
List<Student> studentList= dao.selectStudentIf(student);
for (Student stu:studentList) {
System.out.println("if==="+stu);
}
}
2)动态 SQL 之<where>
(<if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后
的所有
<if/>
条件均为
false
,而
where
后若又没有
1=1
子句,则
SQL
中就会只剩下一个空的
where
,
SQL
出错。所以,在
where
后,需要添加永为真子句
1=1
,以防止这种情况的发生。但当数据量很大时,会
严重影响查询效率。
使用
<where/>
标签,在有查询条件时,可以自动添加上
where
子句;没有查询条件时,不会添加
where
子句。需要注意的是,第一个
<if/>
标签中的
SQL
片断,可以不包含
and
。不过,写上
and
也不错,
系统会将多出的
and
去掉。但其它
<if/>
中
SQL
片断的
and
,必须要求写上。否则
SQL
语句将拼接出错
。
语法:
<where>
其他动态
sql </where>
)
接口方法:
//where 的使用
List<Student> selectStudentWhere(Student student);
mapper
文件:
<!--
where: <where> <if> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.zsz.domain.Student">
select id,name,age,email from student
<where>
<if test="name != null and name !=''">
and name =#{name}
</if>
<if test="age > 0">
or age >#{age}
</if>
</where>
</select>
测试方法:
@Test
public void testSelectStudentWhere(){
SqlSession sqlSession= MybatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student student =new Student();
// student.setName("赵六");
// student.setAge(12);
// student.setName("赵六");
// student.setAge(18);
List<Student> studentList= dao.selectStudentWhere(student);
for (Student stu:studentList) {
System.out.println("if==="+stu);
}
}
3)动态 SQL 之<foreach>
(<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意:
collection
表示要遍历的集合类型
, list
,
array
等。
open
、
close
、
separator
为对遍历内容的
SQL
拼接。
语法:
<
foreach
collection=
"
集合类型
"
open=
"
开始的字符
"
close=
"
结束的字符
"
item=
"
集合中的成员
"
separator=
"
集合成员之间的分隔符
"
>
#{item
的值
}
</
foreach
>
)
(1) 遍历 List<简单类型>
接口方法:
//foreach 用法1
List<Student> selectForeachOne(List<Integer> idList);
mapper
文件:
<!--foreach使用1,List<Integer>-->
<select id="selectForeachOne" resultType="com.zsz.domain.Student">
select * from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
测试方法:
@Test
public void testSelectStudentForeachOne(){
SqlSession sqlSession= MybatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
List<Integer> list=new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
List<Student> studentList= dao.selectForeachOne(list);
for (Student stu:studentList) {
System.out.println("froeach---one==="+stu);
}
}
(2) 遍历 List<对象类型>
接口方法:
//foreach 用法2
List<Student> selectForeachTwo(List<Student> stuList);
mapper 文件:
<!--froeach使用2. List<Student>-->
<!--<select id="selectForeachTwo" resultType="com.zsz.domain.Student">-->
<!--select * from student where id in-->
<!--<foreach collection="list" item="stu" open="(" close=")" separator=",">-->
<!--#{stu.id}-->
<!--</foreach>-->
<!--</select>-->
<!--也可以自己拼接sql语句-->
<select id="selectForeachTwo" resultType="com.zsz.domain.Student">
select * from student where id in (
<foreach collection="list" item="stu" separator=",">
#{stu.id}
</foreach>
)
</select>
测试方法:
@Test
public void testSelectStudentForeachTwo(){
SqlSession sqlSession= MybatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
List<Student> stuList=new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
stuList.add(s1);
s1=new Student();
s1.setId(1006);
stuList.add(s1);
List<Student> studentList= dao.selectForeachTwo(stuList);
for (Student stu:studentList) {
System.out.println("froeach---two==="+stu);
}
}
3)动态 SQL 之代码片段
(<sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用
<include/>
子标签。该
<sql/>
标签可以定义
SQL
语句中的任何部分,所以
<include/>
子标签可以放在动态
SQL
的任何位置。
)
接口方法:
List<Student> selectForeachTwo(List<Student> stulist);
mapper 文件:
<!--创建 sql 片段 id:片段的自定义名称-->
<!--定义sql片段-->
<sql id="studentSql">
select id,name, age, email from student
</sql>
<sql id="studentSqlOne">
id,name, age, email
</sql>
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" /> where id in (
<foreach collection="list" item="stu" >
#{stu.id},
</foreach>
-1 )
</select>
测试方法:
@Test
public void testSelectForTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> stuList = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
s1.setName("lisi");
stuList.add(s1);
s1 = new Student();
s1.setId(1005);;
s1.setName("zs");
stuList.add(s1);
List<Student> students = dao.selectForeachTwo(stuList);
for(Student stu:students){
System.out.println("foreach--two ==="+stu);
}
}