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,使用映射 ...
随机推荐
- python3+selenium入门14-上传下载文件
上传文件一种方式是通过定位input标签,然后使用send_keys()方法传入需要上传文件的路径.另一种是使用第三方插件去上传文件.下面看下imput标签的方式.工具可以自己查下. <!DOC ...
- <TCP/IP>DHCP动态主机配置协议
坚持是一种好习惯 大家都知道,为了上网我们是需要提交一些配置信息的,如IP地址,子网掩码,DNS服务器等,这些是一个主机能够在Internet上运行并给用户提供常用服务(比如web和Email)的基本 ...
- mybatis打印SQL日志
在配置的log4j输出时,不能打印SQL信息,在mybatis-config.xml中添加如下配置即可 <settings> <setting name="logImpl& ...
- 压缩JS的eclipse插件
主页:http://jscompressor.oncereply.me/ Update site: http://jscompressor.oncereply.me/update/
- 运输层TCP/UDP
UDP:用户数据报协议 客户不与服务器建立连接,它只管用函数sendto给服务器发送数据报,此函数要求目的地址(服务器)作为其参数.类似的,服务器不从客户接受连接,它只管调用函数recvfrom,等待 ...
- Laravel-Excel 导入 Excel 文件----为什么只获取到最后一行数据?
### 今天使用了Laravel-Excel 到类文件,想做一个excel 文件到导入和导出,但是看了 官方到文档示例,自己做了一下,发现 只取到到最后一行到数据, 有点摸不着头脑! 网上找了一下, ...
- SpringCloud的版本
Spring Cloud 项目目前仍然是快速迭代期,版本变化很快.这里整理一下版本相关的东西,备忘一下. 大版本 版本号规则 Spring Cloud并没有熟悉的数字版本号,而是对应一个开发代号. C ...
- CSS入门(二)
一.组合选择器 每个选择器位可以是任意基础选择器或选择器组合 1.群组选择器 可以一次性控制多个选择器 选择器之间用逗号(,)隔开 div,.d1,#div{ color:red; } 2.子代(后代 ...
- checkstyle.xml Code Style for Eclipse
1. Code Templates [下载 Code Templates] 打开 Eclipse -> Window -> Preferences -> Java -> Cod ...
- Confluence 6 重构索引缓慢
你的索引构建是否需要很长时间?索引构建需要的时间是由下面的一些因素确定的: 你 Confluence 安装实例中的页面数量. 附件的数量,类型和大小. Confluence 安装实例可用的内存大小. ...