通过mybatis提供的< if > ,< where >,< foreach >标签对条件做出判断以实现动态拼接SQL语句,主要用于解决查询条件不确定的情况,它会根据用户提交的查询条件进行查询。其主要是SQL语句where关键字后面部分发生变化。
在映射文件中的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
重点:特别是对于小于号(<),在 XML 文件中是绝不能出现的。否则解析 映射文件 会出错。
< | 小于 | <; |
---|---|---|
> | 大于 | >; |
>= | 大于等于 | >;= |
<= | 小于等于 | <;= |
<if test="判断java对象的属性值">
部分sql语句
if>
List<Student> selectStudentIf(Student student);
<select id="selectStudentIf" resultType="Student">
<include refid="studentSql"/>
where
<if test="name!=null and name!=''">
name=#{name}
if>
<if test="age>0">
or age>#{age}
if>
select>
这里定义了SQL语句代码片段,方便以后调用,避免代码冗余
使用步骤:
1.先定义 < sql id=“自定义名称唯一”> sql语句, 表名,字段等 < /sql>
2.再使用, < include refid=“id的值” />
<sql id="studentSql" >
select id,name,age,email from student
sql>
@Test
public void testSelectStudenIf(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("李四");
student.setAge(20);
List<Student> studentList = dao.selectStudentIf(student);
for (Student student1:studentList){
System.out.println("学生if="+student1);
}
}
这里如把测试方法中的代码姓名这段代码注释掉:
Student student = new Student();
//student.setName("李四");
student.setAge(20);
List<Student> studentList = dao.selectStudentIf(student);
那么执行的SQL语句则会出错:
SQL:select id,name,age,email from student where or age>?
缺陷:
当后面一个if语句不满足或者都不满足时,SQL语句会拼接成
select id,name,age,email from student where or age>?
select id,name,age,email from student where
这样的SQL语句明显是错误的
小技巧:
可以在where后面加入一个满足条件(真子句),例如:where id>0
这样SQL语句就变成了可执行语句了
select id,name,age,email from student where id>0 or age>?
但当数据量很大时,会严重影响查询效率。
改进后的映射文件为:
<select id="selectStudentIf" resultType="Student">
<include refid="studentSql"/>
where id>0
<if test="name!=null and name!=''">
and name=#{name}
if>
<if test="age>0">
or age>#{age}
if>
select>
里面where关键字后面添加了一个真子句id>0并在name前面加多了and
这样执行SQL语句则变成:
SQL:select id,name,age,email from student where id>0 or age>?
<where>
其他动态 sql
where>
< where >:解决< if >标签带来的小缺陷
< where > 用来包含 多个< if> 的
1、当多个 if 有一个成立的,< where >会自动增加一个WHERE关键字
2、当后面 if 条件有些不成立时,可以去掉 if 中多余的 and ,or等
3、当后面的 if 条件都不满足时,WHERE关键字也会去掉
List<Student> selectStudentWhere(Student student);
<select id="selectStudentWhere" resultType="Student">
<include refid="studentSql">include>
<where>
<if test="name!=null and name!=''">
name=#{name}
if>
<if test="age>0">
or age>#{age}
if>
where>
select>
@Test
public void testSelectStudenWhere(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
//student.setName("李四");
student.setAge(20);
List<Student> studentList = dao.selectStudentWhere(student);
for (Student student1:studentList){
System.out.println("学生where="+student1);
}
}
<foreach collection="" open="" close="" item="" separator="">
#{item 的值}
foreach>
< foreach >标签用于实现对于数组与集合的遍历,主要用在sql语句的 in 语句中
例如:查询学生 id 是 1001,1002,1003
select * from student where id in (1001,1002,1003)
这里定义一个测试方法来拼接上面的SQL语句
@Test
public void testfor(){
List<Integer> list=new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
//String sql = "select * from student where id in(1001,1002,1003);
String sql ="select * from student where id in";
StringBuilder builder = new StringBuilder(sql);
int init=0;
int len=list.size();
//添加开始的(
builder.append("(");
for (Integer i:list){
builder.append(i).append(",");
}
//将最后一个逗号删除
builder.deleteCharAt(builder.length()-1);
//循环结束
builder.append(")");
sql = builder.toString();
System.out.println("sql=="+sql);
}
显然以上代码很长很臭,下面进行改进…
用法一:遍历 List<简单类型>
List<Student> selectStudentForeachOne(List<Integer> list);
<select id="selectStudentForeachOne" resultType="Student">
<include refid="studentSql"/> where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
foreach>
select>
解析标签中的属性:
1、collection:表示接口中的方法参数的类型,
如果是数组使用array , 如果是list集合使用list
2、item:自定义的,表示数组和集合成员的变量,相当于Integer i中的 i 变量
for (Integer i:list){
builder.append(i).append(",");
}
3、open:循环开始是的字符“(”
4、close:循环结束时的字符“)”
5、separator:集合成员之间的分隔符“,”
@Test
public void testSelectStudenForeachOne(){
SqlSession sqlSession = MyBatisUtil.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.selectStudentForeachOne(list);
for (Student student1:studentList){
System.out.println("学生foreachone="+student1);
}
}
用法二:遍历 List<对象类型>
List<Student> selectStudentForeachTwo(List<Student> studentlist);
<select id="selectStudentForeachTwo" resultType="Student">
<include refid="studentSql"/> where id in (
<foreach collection="list" item="stu" separator=",">
#{stu.id}
foreach>
)
select>
注意:这里 item 的值 stu 只是对应的Java对象
@Test
public void testSelectStudenForeachTwo(){
SqlSession sqlSession = MyBatisUtil.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(1002);
stulist.add(s2);
List<Student> studentList = dao.selectStudentForeachTwo(stulist);
for (Student student1:studentList){
System.out.println("学生foreachtwo="+student1);
}
}
如有不足之处请大家指正哈!