文章目录
动态SQL
MyBatis的强大特性之一便是它的动态SQL。使用过JDBC或其他类似框架的人都会知道,根据不同条件拼接SQL语句时不仅不能忘了必要的空格,还要注意省略掉列名列表最后的逗号,处理方式麻烦且凌乱。MyBatis的动态SQL则能让我们摆脱这种痛苦。
在MyBatis 3之前的版本中,使用动态SQL需要学习和了解非常多的标签,现在MyBatis采用了功能强大的OGNL
(Object-Graph Navigation Language)表达式语言消除了许多其他标签,以下是MyBatis的动态SQL在XML中支持的几种标签:
if
choose
(when、oterwise)trim
(where、set)foreach
bind
更多的介绍可以在MyBatis官网进行了解,下面我们来看看它们的具体用法:
- 注意:这里使用的是XML方式进行操作,具体操作方法可以参考前面的博客XML方式的基本用法,其中使用的数据库与前面相同,这里仅仅介绍动态SQL的用法。
if 的用法
if
标签通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件条件,它也经常用于UPDATE语句中判断是否更新某一个字段,还可以在INSERT语句中用来判断是否插入某个字段的值。
在 WHERE 条件中使用 if
-
场景:根据输入的条件去检索用户信息,包含以下4中情况:
- 根据SID查询学生;
- 根据年龄查询学生;
- 根据性别查询学生;
- 更加年龄和性别查询学生。
-
接口文件的写法如下:
public interface StudentMapper {
/**
* 根据输入的条件去检索用户信息
* @param student
* @return
*/
public List<Student> getStudentBySexAndAge(Student student);
}
-
使用
List<Student>
的原因: 有可能所查询到的结果不唯一,因此需要使用集合进行存储。 -
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.tulun.dao.StudentMapper">
<!--
if表达式
一般使用是放在where条件后面
判断参数是否传递使用if test属性(必填)为true或者false
test使用OGNL表达式处理,返回true则进入到if标签的SQL,返回为false则不会进入if标签
参数处理:
假如不存Sage,Ssex: select * from Student where 1=1
假如传Sage,Ssex :select * from Student where 1=1 and Sage = #{Sage} and Ssex = #{Ssex}
假如传Sage:select * from Student where 1=1 and Sage = #{Sage}
假如传Ssex:select * from Student where 1=1 and Ssex = #{Ssex}
-->
<select id="getStudentBySexAndAge" resultType="com.tulun.pojo.Student">
select * from Student where 1=1
<if test="SAge != null">
and SAge = #{SAge}
</if>
<if test="SSex != null">
and SSex = #{SSex}
</if>
</select>
</mapper>
-
注意
select
标签中的where 1 = 1
,此字段是为了防止当test
属性中的条件均为false是SQL语句的正确性,与其配套使用的是if
标签中的语句前面均加上了and连接符。并且,在test
属性中如果需要连接多个判断条件,使用的是and 和 or
而不是&& 和 ||
。 -
进行测试,代码如下:
public class StudentMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void before() {
//mybatis配置文件
String resource = "mybatis-config.xml";
//通过mybatis提供的Resources类来得到配置文件流
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//创建会话工厂,传输mybatis配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void getStudentBySexAndAge() {
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过反射机制来获取对应mapper实例
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//传入无参
Student student = new Student();
mapper.getStudentBySexAndAge(student);
//传入一个参数SSex
Student student = new Student();
student.setSSex("nan");
mapper.getStudentBySexAndAge(student);
//传入一个参数SAge
Student student = new Student();
student.setSAge(10);
mapper.getStudentBySexAndAge(student);
//传入两个参数SSex和SAge
Student student = new Student();
student.setSAge(10);
student.setSSex("nan");
mapper.getStudentBySexAndAge(student);
}
}
- 执行结果如下:
另外,if
标签还可以与UPDATE和INSERT标签联用,用法与上面的用法类似,这里就不再一一列举了。我们接着看下一个标签。
choose 的用法
上面的if
标签提供了基本的条件判断,但是它无法实现if...else
、if...else...
的逻辑,要想实现这样的逻辑,就需要用到choose when otherwise
标签。
choose
元素中包含when
和otherwise
两个标签,一个choose
中至少有一个when
,有0个或者1个otherwise
。
下面来看看具体用法:
-
场景:以上面
if
标签的场景继续进行说明。 -
接口文件:
public interface StudentMapper {
/**
* 根据输入的条件去检索用户信息
* @param student
* @return
*/
public List<Student> getStudentBySexAndAge(Student student);
}
- 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.tulun.dao.StudentMapper">
<select id="getStudentBySexAndAge" resultType="com.tulun.pojo.Student">
select * from Student where 1 = 1
<choose>
<when test="SAge != null">
and SAge = #{SAge}
</when>
<when test="SSex != null