一、什么是动态SQL
动态SQL,通过MyBatis提供的各种标签队条件作出判断以实现动态拼接SQL语句。这里的条件判断使用的表达式为OGNL表达式。常用的动态SQL标签有<if>、<where>、<choose/>、<foreach>等。
二、动态SQL的好处
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行
查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行
排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题。
三、常用的动态SQL标签方法演示
1.动态sql-if
<if>是判断条件的,
语法<if test="判断java对象的属性值">
部分sql语句
</if>
a.在接口中定义一个方法
//动态sql-if,使用java对象作为参数
List<Student> selectStudentIf(Student student);
b.在mapper文件中编写映射信息
<!--if
<if test="使用参数java对象的属性值作为判断条件, 语法 属性=xxx值">
-->
<select id="selectStudentIf" resultType="com.example.domain.Student">
select id, name, email, age from student
where id>0 /*id > 0:避免第一条判断不执行时,sql语句会发生错误,如where and age>?(错误语法)*/
<if test="name !=null and name !=''">
and name = #{name}
</if>
<if test="age>0">
and age > #{age}
</if>
</select>
c.编写测试类
@Test
public void testSelectStudentsIf() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("李四");
student.setAge(18);
List<Student> students = dao.selectStudentIf(student);
for(Student stu : students){
System.out.println("if=="+stu);
}
}
2.动态sql-where
<where>标签用来包含多个<if>的,当多个if有一个成立时,<where>会自动增加一个where关键字,并去掉if中多余的 and,or等
a.在接口中定义一个方法
//动态sql-where
List<Student> selectStudentWhere(Student student);
b.在mapper文件中编写映射信息
<!--
where:<where><if></if>...<where>
-->
<select id="selectStudentWhere" resultType="com.example.domain.Student">
select id, name, email, age from student
<where>
<if test="name !=null and name !=''">
and name = #{name}
</if>
<if test="age>0">
and age > #{age}
</if>
</where>
</select>
c.编写测试类
@Test
public void testSelectStudentsWhere() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
//student.setName("李四");
student.setAge(18);
List<Student> students = dao.selectStudentWhere(student);
for(Student stu : students){
System.out.println("where=="+stu);
}
}
3.动态sql-foreach
<foreach>循环Java中的数值,list集合的,主要用在sql的in语句中
sql中语句是: select * from student where id in(1001,1002,1003);
在开始foreach前先了解然后通过字符串拼接的方法来得到上面的语句
@Test
public void testfor(){
List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
//select * from student where id in(1001,1002,1003)
String sql = "select * from student where id in";
StringBuilder builder = new StringBuilder("");
//添加开始的 '('
builder.append("(");
for(Integer i : list){
builder.append(i).append(",");
}
builder.deleteCharAt(builder.length()-1);
//循环结尾 ')'
builder.append(")");
sql = sql + builder.toString();
System.out.println("sql=="+sql);
}
foreach本质上用到上面的字符串拼接的方法
<foreach collection="" item="" open="" close="" separator="">
</foreach>
collection : 表示接口中的方法参数的类型,如果是数值使用array,如果是List集合使用list
item : 自定义的,表示数组和集合成员变量
open : 循环开始时的字符
close : 循环结束时的字符
separator : 集合成员之间的分隔符
a.在接口中定义方法
//foreach用法1
List<Student> selectForeachOne(List<Integer> idList);
//foreach用法2
List<Student> selectForeachTwo(List<Student> stuList);
b.在mapper文件中编写映射信息
<!--foreach使用1,List<Integer>-->
<select id="selectForeachOne" resultType="com.example.domain.Student">
select * from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
<select id="selectForeachTwo" resultType="com.example.domain.Student">
select * from student where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</select>
c.编写测试类
@Test
public void testSelectStudentsForEachOne() {
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> students = dao.selectForeachOne(list);
for(Student stu : students){
System.out.println("foreach--one"+stu);
}
}
@Test
public void testSelectStudentsForEachTwo() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> stuList = new ArrayList<>();
Student s1 = new Student();
s1.setId(1001);
stuList.add(s1);
Student s2 = new Student();
s2.setId(1005);
stuList.add(s2);
List<Student> students = dao.selectForeachTwo(stuList);
for(Student stu : students){
System.out.println("foreach--two"+stu);
}
}
4.动态sql-代码片段
sql代码片段,就是复用一些语法
步骤:1.先定义 <sql id="自定义名称唯一"> sql语句 ,表名 , 字段等</sql>
2.再使用,<include refid="id的值">
演示:
<!--定义sql片段-->
<sql id="studentSql">
select id, name, age, email from student
</sql>
<!--if
<if test="使用参数java对象的属性值作为判断条件, 语法 属性=xxx值">
-->
<select id="selectStudentIf" resultType="com.example.domain.Student">
/*select id, name, email, age from student*/
<include refid="studentSql"/>
where id>0 /*id > 0:避免第一条判断不执行时,sql语句会发生错误,如where and age>?(错误语法)*/
<if test="name !=null and name !=''">
and name = #{name}
</if>
<if test="age>0">
and age > #{age}
</if>
</select>