MyBatis - 4.动态SQL
- 动态 SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作。
- 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。
- MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作。
1.if
新建接口
public interface IemployeeMapperDynamicSQL {
public List<employee> getEmpsByConditionIf(employee emp);
}
新建Mapper IemployeeMapperDynamicSQL.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.tangge.Mapper.IemployeeMapperDynamicSQL">
<!--
if
choose (when, otherwise)
trim (where, set)
foreach
-->
<!--public List<employee> getEmpsByConditionIf(employee emp);-->
<select id="getEmpsByConditionIf" resultType="com.tangge.model.employee">
select * from tbl_employee WHERE 1=1
<if test="id != 0">
and id=#{id}
</if>
<!--QGNL中的(和):and 和 && ,XML不支持&&,所以可以写成 &&-->
<if test="lastName != null && lastName != ''">
and last_name like #{lastName}
</if>
<!--QGNL中的(或):or 和 || -->
<if test=" gender ==0 || gender == 1">
and gender = #{gender}
</if>
<if test="email != null">
and email=#{email}
</if>
</select>
</mapper>
---->【测试】:
public static void getEmpsByConditionIf() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
IemployeeMapperDynamicSQL mapper = session.getMapper(IemployeeMapperDynamicSQL.class);
employee employee = new employee(0,"%i%",null,null);
List<employee> employees = mapper.getEmpsByConditionIf(employee);
System.out.println(employees);
/**
* 结果:
* [employee{id=1, lastName='null', email='tom@guigu.com', gender=0, dept=null},
* employee{id=5, lastName='null', email='lily@xwf.com', gender=1, dept=null}]
*/
} finally {
session.close();
}
}
2.choose
类似带了 breack 的 swicth-case
<select id="getEmpsByConditionChoose" resultType="com.tangge.model.employee">
select * from tbl_employee
<where>
<choose>
<when test="id != 0">
id=#{id}
</when>
<when test="lastName != null && lastName != ''">
last_name like #{lastName}
</when>
<when test="email != null">
email=#{email}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</where>
</select>
3.Trim
如果条件后面加and,最后生成的SQL条件也有一条and,我们需要删除掉。
使用 <trim>
标签
<select id="getEmpsByConditionTrim" resultType="com.tangge.model.employee">
select * from tbl_employee
<!--
trim:
- prefix:前缀
- prefixOverrides:前缀覆盖
- suffix:后缀
- prefixOverrides:后缀覆盖
-->
<trim prefix="where" suffixOverrides="and">
<if test="id != 0">
id=#{id} and
</if>
<!--QGNL中的(和):and 和 && ,XML不支持&&,所以可以写成 &&-->
<if test="lastName != null && lastName != ''">
last_name like #{lastName} and
</if>
<!--QGNL中的(或):or 和 || -->
<if test=" gender ==0 || gender == 1">
gender = #{gender} and
</if>
<if test="email != null">
email=#{email} and
</if>
</trim>
</select>
3.1 where
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
3.2.set(封装修改条件)
<!--
set标签:
set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。
(因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)
-->
<update id="updateEmp" >
UPDATE tbl_employee
<set>
<if test="lastName != null && lastName != ''">
last_name = #{lastName},
</if>
<!--QGNL中的(或):or 和 || -->
<if test="gender ==0 || gender == 1">
gender = #{gender},
</if>
<if test="email != null">
email=#{email},
</if>
</set>
<where>
id = #{id}
</where>
</update>
若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:
<trim prefix="SET" suffixOverrides=",">
...
</trim>
4.foreach
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
定义个接口
public List<employee> getEmpsByConditionForeach(List<Integer> list1);
Mapper
<select id="getEmpsByConditionForeach" resultType="com.tangge.model.employee">
select * from tbl_employee WHERE id in
<!--
foreach:
- collection:指定要遍历的集合:list类型的参数会封装在map中,map的key就叫list
- item:将遍历出的元素赋值给指定变量
#{变量名} 当前遍历的元素
- separator:每个元素之间的分隔符
- open:开始的字符前缀
- close:结束字符后缀
- index:
- list: index是list的索引,item是当前值
- map: index是map的key,item是map的value
-->
<foreach collection="list" item="item_id" separator="," open="(" close=")">
#{item_id}
</foreach>
</select>
---->【测试】:
public static void getEmpsByConditionForeach() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
IemployeeMapperDynamicSQL mapper = session.getMapper(IemployeeMapperDynamicSQL.class);
List<Integer> list1 = new ArrayList<>();
list1.add(5);
list1.add(6);
List<employee> rows = mapper.getEmpsByConditionForeach(list1);
//执行的SQL:select * from tbl_employee WHERE id in ( 5 , 6 )
System.out.println(rows);
} finally {
session.close();
}
}
4.1 批量插入使用foreach
接口声明:
public boolean addEmpList(@Param("emps") List<employee> employees);
Mapper
<!--批量插入-->
<!-- public boolean addEmpList(@Param("emps") List<employee> employees);-->
<insert id="addEmpList">
INSERT INTO tbl_employee(last_name,gender,email,dept_id) VALUES
<foreach collection="emps" item="item" separator="," >
(#{item.lastName},#{item.gender},#{item.email},#{item.dept.departmentId})
</foreach>
</insert>
---->【测试】:
public static void addEmpList() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
IemployeeMapperDynamicSQL mapper = session.getMapper(IemployeeMapperDynamicSQL.class);
employee employee = new employee("wwa","sdas@sasa",null);
employee employee1 = new employee("wwc","sdas@sasa",null);
List<employee> emps = new ArrayList<>();
emps.add(employee);
emps.add(employee1);
boolean rows = mapper.addEmpList(emps);
System.out.println(rows);
} finally {
session.close();
}
}
5.内置参数:_parameter 与 _databaseId
public List<employee> getEmpsInnerParameter(employee emp);
配置
<!--
两个内置参数:
- _parameter:代表整个参数
* 单个参数:_parameter就是整个参数
* 多个参数:参数封装一个map,_parameter就代表真个map
- _databaseId:如果config xml配置了databaseIdProvider标签。
* _databaseId代表当前数据库的别名oracle
-->
<!--public List<employee> getEmpsInnerParameter(employee emp);-->
<select id="getEmpsInnerParameter" resultType="com.tangge.model.employee">
<if test="_databaseId=='mysql'">
select * from tbl_employee
<if test="_parameter!=null">
WHERE last_name LIKE #{_parameter.lastName}
</if>
</if>
<if test="_databaseId=='oracle'">
select * from employees
</if>
</select>
---->【测试】:
public static void getEmpsInnerParameter() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
IemployeeMapperDynamicSQL mapper = session.getMapper(IemployeeMapperDynamicSQL.class);
employee employee = new employee(0,"%w%",null,null);
List<employee> employees = mapper.getEmpsInnerParameter(employee);
System.out.println(employees);
} finally {
session.close();
}
}
结果:
DEBUG 08-28 15:46:43,167 ==> Preparing: select * from tbl_employee WHERE last_name LIKE ? (BaseJdbcLogger.java:139)
DEBUG 08-28 15:46:43,192 ==> Parameters: %w%(String) (BaseJdbcLogger.java:139)
DEBUG 08-28 15:46:43,221 <== Total: 3 (BaseJdbcLogger.java:139)
[
employee{id=6, lastName='null', email='wewe@qq.com', gender=1, dept=null},
employee{id=7, lastName='null', email='sdas@sasa', gender=null, dept=null},
employee{id=8, lastName='null', email='sdas@sasa', gender=null, dept=null}
]
6.bind (OGNL 表达式绑定)
上面传参 %w%
employee employee = new employee(0,"%w%",null,null);
Mapper
<if test="_parameter!=null">
WHERE last_name LIKE #{_parameter.lastName}
</if>
然后输出的是
DEBUG 08-28 15:46:43,192 ==> Parameters: %w%(String)
---->【需求】:
:现在我们想要传入参数%w%
变为w
,%
在Mapper里添加。
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文
<select id="getEmpsInnerParameter" resultType="com.tangge.model.employee">
<!--bind使用-->
<bind name="pattern" value="'%' + _parameter.lastName + '%'" />
<if test="_databaseId=='mysql'">
select * from tbl_employee
<if test="_parameter!=null">
WHERE last_name LIKE #{pattern}
</if>
</if>
<if test="_databaseId=='oracle'">
select * from employees
</if>
</select>
7.sql 和 include(抽取可重用的SQL片段)
<select id="getEmpsInnerParameter" resultType="com.tangge.model.employee">
<bind name="pattern" value="'%' + _parameter.lastName + '%'" />
<if test="_databaseId=='mysql'">
<!--
引用外部的SQL
- property:自定义属性
这里${abc} 值 tbl_employee,可以在<sql>里运用
-->
<include refid="employee">
<property name="abc" value="tbl_employee"/>
</include>
<if test="_parameter!=null">
WHERE last_name LIKE #{pattern}
</if>
</if>
<if test="_databaseId=='oracle'">
select * from employees
</if>
</select>
<!--
抽取可重用的SQL片段,方便引用
- <sql>抽取:经常查询的列名,或者插入用的列名抽取出来方便引用
- <include>:引用抽取的SQL
- <include>还可以定义<property>,sql内部标签可以使用 ${prop}
-->
<sql id="employee">
select * from ${abc}
</sql>
MyBatis - 4.动态SQL的更多相关文章
- MyBatis的动态SQL详解
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它 ...
- Mybatis解析动态sql原理分析
前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...
- mybatis 使用动态SQL
RoleMapper.java public interface RoleMapper { public void add(Role role); public void update(Role ro ...
- MyBatis框架——动态SQL、缓存机制、逆向工程
MyBatis框架--动态SQL.缓存机制.逆向工程 一.Dynamic SQL 为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句.最常用的就是:where和if标签 1.参考 ...
- 使用Mybatis实现动态SQL(一)
使用Mybatis实现动态SQL 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 写在前面: *本章节适合有Mybatis基础者观看* 前置讲解 我现在写一个查询全部的 ...
- MyBatis探究-----动态SQL详解
1.if标签 接口中方法:public List<Employee> getEmpsByEmpProperties(Employee employee); XML中:where 1=1必不 ...
- mybatis中的.xml文件总结——mybatis的动态sql
resultMap resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功. 如果sql查询字段名和pojo的属性名不一致,可以通过re ...
- mybatis.5.动态SQL
1.动态SQL,解决关联sql字符串的问题,mybatis的动态sql基于OGNL表达式 if语句,在DeptMapper.xml增加如下语句; <select id="selectB ...
- MyBatis的动态SQL详解-各种标签使用
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有: if choose(when,otherwise) ...
- 利用MyBatis的动态SQL特性抽象统一SQL查询接口
1. SQL查询的统一抽象 MyBatis制动动态SQL的构造,利用动态SQL和自定义的参数Bean抽象,可以将绝大部分SQL查询抽象为一个统一接口,查询参数使用一个自定义bean继承Map,使用映射 ...
随机推荐
- Python学习-环境搭建(IronPython)
一.IDE环境 VS2013 下安装 PTVS 2.2.2 VS 2013 VS2015 已经集成了Python的开发环境 二.安装 IronPython 下载地址:http://ironpytho ...
- inception v1-v3 & Xception
inception v1-v3:通过多尺度卷积核学习不同尺度的空间信息并进行耦合:通过多个小卷积核来代替大卷积核的功能从而降低计算量: 通常,在一组特征图上进行卷积需要三维的卷积核,也即卷积核需要同时 ...
- tar.gz压缩,查看,解压
本次使用的压缩格式是*.tar.gz,用到的命令如下: 压缩: tar -czf jpg.tar.gz *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个g ...
- Sql Server中的数据类型和Mysql中的数据类型的对应关系(转)
Sql Server中的数据类型和Mysql中的数据类型的对应关系(转):https://blog.csdn.net/lilong329329/article/details/78899477 一.S ...
- 设计模式C++学习笔记之十九(State状态模式)
19.1.解释 概念:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类. main(),客户 CLiftState,电梯状态抽象类 CCloseingState,电梯门关闭 ...
- 提高Django高并发性的部署方案(Python)
方案: nginx + uWSGI 提高 Django的并发性 1. uWSGI : uWSGI是一个web服务器,实现了WSGI协议.uwsgi协议.h ...
- 在本地SharePoint 2013 搭建App开发环境
1.环境描述: SharePoint服务器: Windows Server 2012 R2+SharePoint 2013 IP:192.168.1.180,域控:ser.com 开发环境: Wind ...
- 035_lua快速入门
执行下面的脚本用luajit test.lua即可 一.变量及逻辑运算 --number, string, boolean, table, function, thread, userdata, ni ...
- 前端 -----jQuery的事件绑定和解绑
11-jQuery的事件绑定和解绑 1.绑定事件 语法: bind(type,data,fn) 描述:为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数. 参数解释: type (S ...
- 监听 input上传文件, 获取文件名称,
<div class="import-box pr" > <span class="model-address-txt">导入文件:&l ...