【Mybatis】13 动态SQL
还是先准备演示环境
数据库:
CREATE TABLE `t_user` (
`id` int NOT NULL AUTO_INCREMENT,
`last_name` varchar(10) DEFAULT NULL,
`gender` int DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
【数据随便加,注意写一个同名不同性的】
实体类
package cn.dai.pojo; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias; /**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 30 - 20:35
*/ @Alias("user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User { private Integer id;
private String last_name;
private Boolean gender;
}
映射接口
package cn.dai.mapper; import cn.dai.pojo.User; import java.util.List; /**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 30 - 20:36
*/
public interface UserMapper { List<User> getUsersByNameAndGender(User user);
}
映射器
<?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接口名称-->
<mapper namespace="cn.dai.mapper.UserMapper"> <select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
WHERE
last_name = #{last_name}
and gender = #{gender}
</select>
</mapper>
测试
import cn.dai.mapper.UserMapper;
import cn.dai.pojo.User;
import cn.dai.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test; import java.util.List; /**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 30 - 21:17
*/
public class BuildTest { @Test
public void queryUsersByNameAndGender(){
SqlSession sqlSession = MybatisUtil.getSqlSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> users = userMapper.getUsersByNameAndGender(new User(null, "阿伟", 1)); for (User user: users) {
System.out.println(user);
} sqlSession.close();
}
}
结果
1、IF 语句
默认情况性别的状态码就是1和0
但是不排除乱写的情况,比如注入其他的数字
这时候可以使用动态SQL帮助我们进行一个逻辑控制
如果注入了不符号我们期望的数值,那么将设置为默认值即可
<?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接口名称-->
<mapper namespace="cn.dai.mapper.UserMapper"> <select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
WHERE
last_name = #{last_name}
<if test="gender==0 or gender==1">
and gender = #{gender}
</if> </select>
</mapper>
似乎mybatis这样查询的会是0&1的结果,如果我们希望只查询0,那么就不要写1即可
另外两个条件可以使用IF
<select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
WHERE
<if test="last_name != null">
last_name = #{last_name}
</if> <if test="gender==0 or gender==1">
and gender = #{gender}
</if> </select>
2、WHERE 语句
如果出现的元数据问题不是我们的性别状态,而是前面的姓名问题
姓名注入了空值,那么程序将会异常中断
直接打印这样的错误信息
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5
### The error may exist in mapper/UserMapper.xml
### The error may involve cn.dai.mapper.UserMapper.getUsersByNameAndGender-Inline
### The error occurred while setting parameters
### SQL: SELECT * FROM t_user WHERE
### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5
其实道理也很简单
我们为了避免这样的SQL语法错误,提供了更好的动态SQL标签:使用Where
<?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接口名称-->
<mapper namespace="cn.dai.mapper.UserMapper"> <select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
<where>
<if test="last_name != null">
last_name = #{last_name}
</if> <if test="gender==0 or gender==1">
and gender = #{gender}
</if>
</where>
</select> </mapper>
查询结果:
当姓名为空,就按照下面的性别条件查询
不再有异常问题
这是因为WHERE标签,可以动态的实现AND或者OR条件连接
但是不要删除了条件连接,这样还是会报语法错误
所以WHERE只是简单的判断和补充
3、TRIM 语句
可以动态的添加删除内容
- prefix 前置添加
- suffix 后置添加
- suffixOverrides 前置删除
- prefixOverrides 后置删除
<select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
<trim suffixOverrides="and" prefix="where">
<if test="last_name != null">
last_name = #{last_name} and
</if> <if test="gender==0 or gender==1">
gender = #{gender}
</if>
</trim>
</select>
不是很能明白前缀和后缀
4、CHOOSE(WHEN & OTHERS) 语句
可以执行多个条件判断,问题是只能有一个条件适用
【根据上面的结果能推断的适用条件是搭配其他的前置条件,并成为最后一个多选一的关键条件】
就纯语法案例:
- 有名字,按名字查
- 没有按性别查
- 再没有自己写一个条件查
<select id="getUsersByNameAndGender" parameterType="user" resultType="user">
SELECT
*
FROM
t_user
WHERE
<choose>
<when test="last_name != null">
last_name = #{last_name}
</when> <when test="gender == 1 or gender == 0">
gender = #{gender}
</when> <otherwise>
id between 1 and 10
</otherwise>
</choose>
</select>
测试一个上述条件都没有最后执行otherwise的结果
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 11939193.
[cn.dai.mapper.UserMapper.getUsersByNameAndGender]-==> Preparing: SELECT * FROM t_user WHERE gender = ?
[cn.dai.mapper.UserMapper.getUsersByNameAndGender]-==> Parameters: 0(Integer)
[cn.dai.mapper.UserMapper.getUsersByNameAndGender]-<== Total: 4
User(id=1, last_name=阿伟, gender=0)
User(id=3, last_name=杰哥, gender=0)
User(id=4, last_name=阿强, gender=0)
User(id=5, last_name=虞姬, gender=0)
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@b62d79]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 11939193 to pool. Process finished with exit code 0
5、SET 语句
用于删除更新多个字段的逗号
<update id="updateUserById" parameterType="int" >
UPDATE
t_user
<set>
<if test="last_name != null">
last_name = #{last_name},
</if> <if test="gender == 1 or gender == 0">
gender = #{gender}
</if>
</set>
WHERE
id = #{id}
</update>
动态的删除逗号分隔
6、FOREACH语句
在之前的一个动态SQL标签中
我们这样进行筛选一个连续的部分,或者说是使用in语句也可以
Mybatis提供一个FOREACH标签来完成这个功能
List<User> getUserByFragment(List<Integer> id);
查看约束我们发现这个遍历标签只允许集合类型
映射器配置
<select id="getUsersByFragment" parameterType="int" resultType="user" >
SELECT *
FROM t_user
<where>
id in
<foreach
collection="id"
item="el"
index="("
separator=","
close=")"
>
#{el}
</foreach>
</where> </select>
截图说明:
但是这样的结果更像是拼接出来的一样,估计底层就是拼接吧。。。
上面的这些都不再做演示了
Script标签
使用注解SQL实现时,可以使用script标签完成动态SQL
比如:
@Update({"<script>",
"update Author",
" <set>",
" <if test='username != null'>username=#{username},</if>",
" <if test='password != null'>password=#{password},</if>",
" <if test='email != null'>email=#{email},</if>",
" <if test='bio != null'>bio=#{bio}</if>",
" </set>",
"where id=#{id}",
"</script>"})
void updateAuthorValues(Author author);
SQL片段
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。
参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。
比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
这个 SQL 片段可以在其它语句中使用,例如:
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
也可以在 include 元素的 refid 属性或内部语句中使用属性值,例如:
<sql id="sometable">
${prefix}Table
</sql> <sql id="someinclude">
from
<include refid="${include_target}"/>
</sql> <select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>
【Mybatis】13 动态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,使用映射 ...
随机推荐
- npm包管理器 切换npm源 使用nrm来管理npm镜像源
npm是NodeJs项目模块管理工具,它已经集成了nodejs安装包中,在npm从从5.2版开始,增加了 npx 命令(解决的主要问题,就是调用项目内部安装的模块,很多工具不再需要npm -g 全局来 ...
- 讲课 PPT 公开啦
目前限于时间原因,只在 Github Pages 上托管了. 之后有时间会托管到 pythonanywhere 上,因为 Github Pages 是在太慢了.
- 小米 红米 Redmi MIUI 5G开关
小米 红米 Redmi MIUI 5G开关 1.打开手机拨号界面输入 *#*#54638#*#* 之后拨号界面底部会显示display 5G network menu (显示5G网络菜单) 注意:先是 ...
- python allure将生成报告和打开报告写到命令文件,并默认使用谷歌打开
背景: 使用python + pytest +allure,执行测试用例,并生成测试报告: allure报告要从收集的xml.json等文件,生成报告,不能直接点击报告的index.html,打开的报 ...
- Bloom Filter布隆过滤器
简介 本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "某样东西一定不存在或者可 ...
- 算法金 | A - Z,115 个数据科学 机器学习 江湖黑话(全面)
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 机器学习本质上和数据科学一样都是依赖概率统计,今天整整那些听起来让人头大的机器学习江湖 ...
- python重拾第十天-协程、异步IO
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 引子 到目前为止,我们已经学了网络并发编程的2个套路, 多进程,多线程,这哥俩的优势和劣势都非常的明显,我们一起来回顾 ...
- 如何免费在 arm 官网上下载合适的手册
背景 有时候搞底层配置的时候(尤其是uboot),需要查阅文档. 这里介绍如何在arm 官网进行查找下载,这样就可以不用去 CSDN 了. 实际上CSDN上的一些文档就是这样下载下来二次收费的,强烈谴 ...
- 设备树DTS 学习:学习总结(应用篇)
设备树DTS 学习:学习总结(应用篇) 背景 经过前几章的学习,我们可以说是掌握了设备树的基础用法,现在作为总结回顾. 1.设备树DTS 学习:有关概念 介绍了什么是设备树,设备树的作用,如何编译设备 ...
- C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏
前言 今天大姚给大家分享一款由C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏:SeeSharpSnake. 项目特点 该仓库中的项目文件和脚本可以用多种不同的配置构建相同的游戏,每个配置生成的输出大 ...