1、<if>标签
MyBatis中的<if>元素类似于Java中的 if 语句。<if>标签中的test属性是判断的表达式,有以下两个注意点:
在表达式中使用字母and而非使用&符号
字符串判断双引号套单引号使用
示例:查找年龄大于30或地址在北京的学生信息。
(1)在IStudentDao下添加方法。
List<Student> findByCondition(Student student);
(2)在studentMapper.xml中添加映射语句。
<select id="findByCondition" parameterType="com.day1.entity.Student" resultType="com.day1.entity.Student">
select * from t_student where 1=1
<if test="age > 0">
and age > #{age}
</if>
<if test="address != null and address != ''">
or address = #{address}
</if>
</select>
说明: 上述查询语句中,在where后面添加了1=1,这是为了防止sql语句出错。如果没有1=1,那么当age和address为空时,此时sql语句就会变为select * from t_student where,这样的语句是错误的。
(3)添加测试方法。
@Test
public void testFindByCondition() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
//5、使用代理对象执行方案
Student student = new Student();
student.setAge(30);
student.setAddress("北京");
List<Student> students = studentDao.findByCondition(student);
for(Student stu : students){
System.out.println(stu);
}
//6、释放资源
sqlSession.close();
in.close();
}
2、choose、when、otherwise标签
choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。其基本结构如下:
<!--使用choose、when、otherwise元素根据条件动态查询用户信息-->
<select id="selectStudent" resultType="com.day1.entity.Student" parameterType= "com.day1.entity.Student">
select * from user where 1=1
<choose>
<when test="条件1">
...
</when>
<when test="条件1">
...
</when>
<otherwise>
...
</otherwise>
</choose>
</select>
示例:查找数据库表中名字以张开头并且地址在北京的学生。
(1)在IStudentDao下添加方法。
List<Student> getStudentByChoose(Student student);
(2)在studentMapper.xml中添加映射语句。
<select id="getStudentByChoose" parameterType="com.day1.entity.Student" resultType="com.day1.entity.Student">
select * from t_student where
<choose>
<when test="username != null and username != ''">
username like #{username}
</when>
<when test="address != null and address != ''">
and address = #{address}
</when>
<otherwise>
</otherwise>
</choose>
</select>
(3)添加测试方法。
@Test
public void testFindByChoose() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
//5、使用代理对象执行方案
Student student = new Student();
student.setUsername("张%");
student.setAddress("北京");
List<Student> students = studentDao.getStudentByChoose(student);
for(Student stu : students){
System.out.println(stu);
}
//6、释放资源
sqlSession.close();
in.close();
}
3、<where> 元素
<where> 元素的作用是会在写入 <where> 元素的地方输出一个 where 语句,此外不需要考虑 <where> 元素里面的条件输出是什么样子的,MyBatis 将智能处理。如果所有的条件都不满足,那么 MyBatis 就会查出所有的记录,如果输出后是以 and 开头的,MyBatis 会把第一个 and 忽略。如果是以 or 开头的,MyBatis 也会把它忽略,而且在 <where> 元素中不需要考虑空格的问题,MyBatis 将智能加上。
示例:查找名字为齐菲,年龄大于30,地址在河北的学生信息。
(1)在IStudentDao下添加方法。
List<Student> getStudentUseWhere(Student student);
(2)在studentMapper.xml中添加映射语句。
<select id="getStudentUseWhere" resultType="com.day1.entity.Student">
SELECT * FROM t_student
<where>
<if test="username != null">
username = #{username}
</if>
<if test="age > 0">
AND age > #{age}
</if>
<if test="address != null ">
AND address like #{address}
</if>
</where>
</select>
(3)添加测试方法。
@Test
public void testFindByWhere() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
//5、使用代理对象执行方案
Student student = new Student();
student.setUsername("齐菲");
student.setAge(30);
student.setAddress("河北");
List<Student> students = studentDao.getStudentUseWhere(student);
for(Student stu : students){
System.out.println(stu);
}
//6、释放资源
sqlSession.close();
in.close();
}
4、<trim> 元素
<trim> 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix。它可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides。正因为 <trim> 元素有这样的功能,所以也可以非常简单地利用 <trim> 来代替 <where> 元素的功能。
示例:查找学生名字刘开头的,且地址为北京
(1)在IStudentDao下添加方法。
List<Student> getStudentByTrim(Student student);
(2)在studentMapper.xml中添加映射语句。
<!--使用trim元素根据条件动态查询用户信息-->
<select id="getStudentByTrim" resultType="com.day1.entity.Student" parameterType="com.day1.entity.Student">
select * from t_student
<trim prefix="where" prefixOverrides = "and | or">
<if test="username!=null and username!=''">
and username like #{username}
</if>
<if test="address!=null and address!=''">
and address=#{address}
</if>
</trim>
</select>
(3)添加测试方法。
@Test
public void testFindByTrim() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
//5、使用代理对象执行方案
Student student = new Student();
student.setUsername("刘%");
student.setAddress("北京");
List<Student> students = studentDao.getStudentByTrim(student);
for(Student stu : students){
System.out.println(stu);
}
//6、释放资源
sqlSession.close();
in.close();
}
5、 <set> 元素
<set> 元素在动态 update 语句中可以动态更新列。
示例:修改王可的地址为浙江。
(1)在IStudentDao下添加方法。
int updateStudent(Student student);
(2)在studentMapper.xml中添加映射语句。
<update id="updateStudent">
update t_student
<set>
<if test="address != null">
address = #{address}
</if>
</set>
where username = #{username}
</update>
(3)添加测试方法。
@Test
public void testFindBySet() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
//5、使用代理对象执行方案
Student student = new Student();
student.setUsername("王可");
student.setAddress("浙江");
int sum = studentDao.updateStudent(student);
System.out.println("修改了" + sum + "记录");
//6、释放资源
sqlSession.close();
in.close();
}
6、错误总结
报错信息:Mapper method 'com.day1.dao.IStudentDao.updateStudent attempted to return null from a method with a primitive return type (int).
错误写法:
<select id="updateStudent" resultType="int">
update t_student
<set>
<if test="address != null">
address = #{address}
</if>
</set>
where username = #{username}
</select>
<select id="updateStudent">
update t_student
<set>
<if test="address != null">
address = #{address}
</if>
</set>
where username = #{username}
</select>
正确写法:
<update id="updateStudent">
update t_student
<set>
<if test="address != null">
address = #{address}
</if>
</set>
where username = #{username}
</update>