简介
•动态SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作。
•动态SQL 元素和使用JSTL 或其他类似基于XML 的文本处理器相似。
•MyBatis 采用功能强大的基于OGNL
的表达式来简化操作。
–if
–choose (when, otherwise)
–trim (where, set)
–foreach
MyBatis-动态SQL
if
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
choose (when, otherwise)
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
trim (where,set)
where
select * from mybatis.blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
set
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
trim
所谓的动态SQL,本质还是SQL语句 , 只是我们可以在SQL层面,去执行一个逻辑代码
Foreach
select * from user where 1=1 and
<foreach item="id" collection="ids"
open="(" separator="or" close=")">
#{id}
</foreach>
(id=1 or id=2 or id=3)
<!--
select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)
我们现在传递一个万能的map , 这map中可以存在一个集合!
-->
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
•动态SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建IN 条件语句的时候。
-
当迭代列表、集合等可迭代对象或者数组时
–index
是当前迭代的次数
,item
的值是本次迭代获取的元素
-
当使用字典(或者Map.Entry对象的集合)时
–index
是键,item
是值
bind
- bind 元素可以从OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
Multi-dbvendor support
•若在mybatis配置文件中配置了databaseIdProvider, 则可以使用“_databaseId”变量,这样就可以根据不同的数据库厂商构建特定的语句
OGNL(Object Graph Navigation Language )对象图导航语言,这是一种强大的
表达式语言,通过它可以非常方便的来操作对象属性。类似于我们的EL,SpEL等
访问对象属性:person.name
调用方法:person.getName()
-
调用静态属性/方法
-
@java.lang.Math@PI
@java.util.UUID@randomUUID()
调用构造方法:new com.atguigu.bean.Person(‘admin’).name
运算符:+,-*,/,%
逻辑运算符:in,not in,>,>=,<,<=,==,!=
注意:xml中特殊符号如”,>,<等这些都需要使用转义字符
访问集合伪属性:
测试
@Test
public void testDynamicSql() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
//select * from tbl_employee where id=? and last_name like ?
//测试if\where
Employee employee = new Employee(1, "Admin", null, null);
/* List<Employee> emps = mapper.getEmpsByConditionIf(employee );
for (Employee emp : emps) {
System.out.println(emp);
}*/
//查询的时候如果某些条件没带可能sql拼装会有问题
//1、给where后面加上1=1,以后的条件都and xxx.
//2、mybatis使用where标签来将所有的查询条件包括在内。mybatis就会将where标签中拼装的sql,多出来的and或者or去掉
//where只会去掉第一个多出来的and或者or。
//测试Trim
/*List<Employee> emps2 = mapper.getEmpsByConditionTrim(employee);
for (Employee emp : emps2) {
System.out.println(emp);
}*/
//测试choose
/*List<Employee> list = mapper.getEmpsByConditionChoose(employee);
for (Employee emp : list) {
System.out.println(emp);
}*/
//测试set标签
/*mapper.updateEmp(employee);
openSession.commit();*/
List<Employee> list = mapper.getEmpsByConditionForeach(Arrays.asList(1,2));
for (Employee emp : list) {
System.out.println(emp);
}
}finally{
openSession.close();
}
}
SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用!
- 使用SQL标签抽取公共的部分
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
- 在需要使用的地方使用Include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
注意事项:
- 最好基于单表来定义SQL片段!
- 不要存在where标签