目前为止可能还看不出mybatis与hibernate相比具有什么优势,甚至觉得mybatis比Hibernate还要麻烦一些(需要手动写sql语句)。
这一节就讲述mybatis的特色之一的动态sql。动态sql运行在sql语句中动态的添加条件。下面通过实例进行说明。
1.新建工程MyBatisPro02,按照前面讲过的配置方法配置好。
2.新建Student类:
package com.test.model;
public class Student {
private Integer id;
private String name;
private Integer age;
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
这里去掉了班级、地址等信息。使用最简单的方式。
3.t_student表还是之前的数据:
4.在实际的开发中查询学生信息的时候,通常都是列出好几种条件供用户选择,用户可能会选择根据几个条件来查询学生信息(比如上一个博客中查询学生信息就有根据id查询,根据gradeId查询。当时写了好几个查询方法,这样的话非常麻烦)。使用动态sql的if条件查询,可以把这些个条件放在一起。StudentMapper中写一个查询接口:
package com.test.mappers;
import java.util.List;
import java.util.Map;
import com.test.model.Student;
public interface StudentMapper {
public List<Student> searchStudents(Map<String,Object> map);
}
这里注意,这个查询学生方法的传入参数是一个map对象,里面是键值对的形式,这样的话可以把查询条件都放在这个map中。5.StudentMapper.xml中实现这个接口:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mappers.StudentMapper">
<resultMap type="Student" id="StudentResult">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<select id="searchStudents" parameterType="Map" resultMap="StudentResult">
select * from t_student
where 1=1
<if test="name!=null">
and name like #{name}
</if>
<if test="age!=null">
and age=#{age}
</if>
<if test="gradeId!=null">
and gradeId = #{gradeId}
</if>
</select>
</mapper>
这里使用if条件查询。使用if进行判断,判断有哪些条件,并动态的拼接sql语句。这里面where后面的1=1,添加这个条件的目的是防止map为空。如果map为空的话,此时拼接的sql语句为:select * from t_student where 1=1,这也是查询所有的学生。如果where后面没有1=1,而map为空的时候,此时拼接的sql为:select * from t_student where ,这个时候就会报错了。
6.写测试方法:
package com.test.service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.test.mappers.StudentMapper;
import com.test.model.Student;
import com.test.util.SqlSessionFactoryUtil;
public class StudentTest {
private static Logger logger = Logger.getLogger(StudentTest.class);
private SqlSession sqlSession = null;
private StudentMapper studentMapper = null;
@Before
public void setUp() throws Exception {
sqlSession = SqlSessionFactoryUtil.openSession();
studentMapper = sqlSession.getMapper(StudentMapper.class);
}
@After
public void tearDown() throws Exception {
sqlSession.close();
}
@Test
public void testSearchStudents() {
logger.info("查询学生(带条件)");
Map<String,Object> map = new HashMap<String,Object>();
//map.put("gradeId", 2);
map.put("name", "%李%");
//map.put("age", 11);
List<Student> studentList = studentMapper.searchStudents(map);
for(Student s:studentList){
System.out.println(s);
}
}
}
在这个测试方法中,我们可以随意的添加查询条件。比如当前是查询名字中有李的学生。如果查询gradeId为2,名字中有李,年龄等于11的学生,就把注释的语句中的注释去掉即可。运行当前的查询名字中有李的学生,查询结果为:
上面通过if查询实现了多条件查询。
6.choose,when 和otherwise 条件
上面通过if查询实现了多条件查询。还有这样一种请求,只能根据一种条件进行查询,但是这种查询条件是可以选择的。(比如可以根据id进行查询或者根据gradeId查询,或者根据名字查询。这里每次查询都只能用一个条件进行查询,但是这个条件是可选的。)这时就要用到choose,when 和otherwise 条件。
6.1StudentMapper中添加查询方法接口:
public List<Student> searchStudents2(Map<String,Object> map);
6.2StudentMapper.xml中实现这个方法:
<select id="searchStudents2" parameterType="Map" resultMap="StudentResult">
select * from t_student
<choose>
<when test="searchBy=='gradeId'">
where gradeId=#{gradeId}
</when>
<when test="searchBy=='name'">
where name like #{name}
</when>
<otherwise>
where age = #{age}
</otherwise>
</choose>
</select>
这里查询学生的时候根据searchBy的值进行判断,当它的值为gradeId的时候,就是根据gradeId进行查询。当它的值为name的时候就是根据name进行查询。如果不是上面的两种情况,就根据age进行查询。
6.3添加测试方法:
@Test
public void testSearchStudents2() {
logger.info("查询学生(带条件)");
Map<String,Object> map = new HashMap<String,Object>();
map.put("searchBy", "age");
map.put("gradeId", 2);
map.put("name", "%李%");
map.put("age", 11);
List<Student> studentList = studentMapper.searchStudents2(map);
for(Student s:studentList){
System.out.println(s);
}
}
这里把几个查询条件都放进去。如果想根据gradeId进行查询,就设置searchBy的值为gradeId。这里设置了searchBy的值是age,就是根据age进行查询。
运行这个测试方法:
这里查询到了年龄为11岁的学生信息。
总结:这一节讲的是动态sql,主要讲了if条件和choose,when 和otherwise 条件。其中if条件能够动态的实现多条件联合查询,choose,when 和otherwise 条件能够实现单条件可选的单条件查询。