动态SQL是MyBatis的强大特性之一,MyBatis3采用了功能强大的基于OGNL的表达式来完成动态SQL。动态SQL主要元素如下表所示:
在使用之前:导入相对应的包:第一个程序相同包
并且代码在原先的基础上进行修改,新建一个com.lzq.utils
包在里面新建一个class类,类名为:MybatisUtils
,相当于将每一个测试当中的公共部分抽离出来放在这一个新的类当中,方法定义为静态方法,在其他类当中调用时不要要实例化。
package com.lzq.utils;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
// 初始化SqlSessionFactory对象
static {
try {
// 使用MyBatis提供的Resources类加载mybatis的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 构建sqlSession的工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取SqlSession对象的静态方法
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
if 元素
在MyBatis中,<if>
元素是最常用的判断语句,它类似于Java中的if语句,主要用于实现某些简单的条件选择。其基本使用示例如下:表示查询说有信息并且对username和jobs进行非空判断。
使用方法:在com.lzq.mapper
包里面的Mapper.xml
文件当中加上一条select语句
<select id="findCustomerByNameAndJobs"
parameterType="com.lzq.po.Customer" resultType="com.lzq.po.Customer">
select * from t_customer where 1=1
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</select>
再新建一个com.lzq.test包里面定义一个测试类:导入相对应的包使用以下方法进行测试
//@Test
public void findCustomerByNameAndJobsTest(){
// 通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 创建Customer对象,封装需要组合查询的条件
Customer customer = new Customer();
customer.setUsername("jack");
customer.setJobs("teacher");
// 执行SqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.lzq.mapper"
+ ".CustomerMapper.findCustomerByNameAndJobs",customer);
//使用foreach进行输出
for (Customer customer2 : customers) {
System.out.println(customer2);
}
session.close();
}
在这里给定的俩个参数,分别是先判断username是否为空:不为空则按username进行查询,如下图所示:
反之当给定的username的值为空值时,则会按照jobs进行查询,可以看到在后面的select语句当中是不会再加上username的限定了:如下图所示:
choose及其子元素
一共包括了<choose>、<when>、<otherwise>
元素。在这里就很类似Java当中的switch case default
代码段了。
简单代码段如下所示:就像switch一般,当满足的条件不同的时候会在最开始的select语句上面加上所框选的代码。
具体代码如下:
<select id="findCustomerByNameOrJobs"
parameterType="com.lzq.po.Customer" resultType="com.lzq.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username !=null and username!=''">
and username like concat ('%',#{username},'%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
测试代码与上述测试if元素的基本相同,修改方法名以及从Mapper.xml中定义了的id即可,测试代码如下所示:当俩者皆为空的时候,会组装otherwise进行条件查询。在后面加上的是phone is not null
,并且会将所有数据查询出来== select * from t_customer
当其中有一项不为空的时候与测试if元素代码一致。
Where和trim元素
在以上代码中,映射文件中编写的SQL后面都加入了“where 1=1”的条件,那么到底为什么要这么写呢?如果将where后“1=1”的条件去掉,那么MyBatis所拼接出来的SQL将会如下所示:
select * from t_customer where and username like concat('%',?, '%')
这样的SQL语句明显存在SQL语法错误,而加入了条件“1=1”后,既保证了where后面的条件成立,又避免了where后面第一个词是and或者or之类的关键词。针对这种情况,MyBatis 提供了 <where>
元素来处理这样的问题,将原先的where 1 =1 删除掉加上where标签即可,如下图所示:
在加上where标签之后,再此运行代码会发现原先的条件会直接变成WHERE如下图所示:
在使用where元素还可以使用trim元素给其加上限定where。
再一次运行测试代码可以看到在控制台输出的where是小写的,而使用where元素输出的是大写的。
上述配置代码中,同样使用<trim>
元素对“where 1=1”
条件进行了替换,<trim>
元素的作用是去除一些特殊的字符串,它的prefix
属性代表的是语句的前缀( 这里使用where来连接后面的SQL片段),而prefixOverrides
属性代表的是需要去除的那些特殊字符串( 这里定义了要去除SQL中的and ),上面的写法和使用<where>
元素基本是等效的。