mybatis注解动态sql_超全MyBatis动态SQL详解
MyBatis 令人喜欢的一大特性就是动态 SQL。在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的。MyBatis 动态 SQL 的出现, 解决了这个麻烦。
MyBatis通过 OGNL 来进行动态 SQL 的使用的。目前, 动态 SQL 支持以下几种标签:
1 数据准备
为了后面的演示, 创建了一个 Maven 项目 mybatis-dynamic, 创建了对应的数据库和表
DROP TABLE IF EXISTS `student`;CREATE TABLE `student` ( `student_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号', `name` varchar(20) DEFAULT NULL COMMENT '姓名', `phone` varchar(20) DEFAULT NULL COMMENT '电话', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', `sex` tinyint(4) DEFAULT NULL COMMENT '性别', `locked` tinyint(4) DEFAULT NULL COMMENT '状态(0:正常,1:锁定)', `gmt_created` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '存入数据库的时间', `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改的时间', `delete` int(11) DEFAULT NULL, PRIMARY KEY (`student_id`)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表';
对应的项目结构
2 if 标签
if 标签是我们最常使用的。在查询、删除、更新的时候很可能会使用到。必须结合 test 属性联合使用。
2.1 在 WHERE 条件中使用 if 标签
这是常见的一种现象, 我们在进行按条件查询的时候, 可能会有多种情况。
2.1.1 查询条件
根据输入的学生信息进行条件检索
- 当只输入用户名时, 使用用户名进行模糊检索;
- 当只输入性别时, 使用性别进行完全匹配
- 当用户名和性别都存在时, 用这两个条件进行查询匹配查询
2.1.2 动态 SQL
接口函数
/** * 根据输入的学生信息进行条件检索 * 1. 当只输入用户名时, 使用用户名进行模糊检索; * 2. 当只输入邮箱时, 使用性别进行完全匹配 * 3. 当用户名和性别都存在时, 用这两个条件进行查询匹配的用 * @param student * @return */ List selectByStudentSelective(Student student);
对应的动态 SQL
select from student where 1=1 and name like concat('%', #{name}, '%') and sex=#{sex}
在此 SQL 语句中, where 1=1 是多条件拼接时的小技巧, 后面的条件查询就可以都用 and 了。
同时, 我们添加了 if 标签来处理动态 SQL
and name like concat('%', #{name}, '%') and sex=#{sex}
此 if 标签的 test 属性值是一个符合 OGNL 的表达式, 表达式可以是 true 或 false。如果表达式返回的是数值, 则0为 false, 非 0 为 true;
2.1.3 测试
@Test public void selectByStudent() { SqlSession sqlSession = null; sqlSession = sqlSessionFactory.openSession(); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student search = new Student(); search.setName("明"); System.out.println("只有名字时的查询"); List studentsByName = studentMapper.selectByStudentSelective(search); for (int i = 0; i < studentsByName.size(); i++) { System.out.println(ToStringBuilder.reflectionToString(studentsByName.get(i), ToStringStyle.MULTI_LINE_STYLE)); } search.setName(null); search.setSex((byte) 1); System.out.println("只有性别时的查询"); List studentsBySex = studentMapper.selectByStudentSelective(search); for (int i = 0; i < studentsBySex.size(); i++) { System.out.println(ToStringBuilder.reflectionToString(studentsBySex.get(i), ToStringStyle.MULTI_LINE_STYLE)); } System.out.println("姓名和性别同时存在的查询"); search.setName("明"); List studentsByNameAndSex = studentMapper.selectByStudentSelective(search); for (int i = 0; i < studentsByNameAndSex.size(); i++) { System.out.println(ToStringBuilder.reflectionToString(studentsByNameAndSex.get(i), ToStringStyle.MULTI_LINE_STYLE)); } sqlSession.commit(); sqlSession.close(); }
只有名字时的查询, 发送的语句和结果
查询的条件只发送了
where 1=1 and name like concat('%', ?, '%')
只有性别时的查询, 发送的语句和结果
查询的条件只发送了
where 1=1 and sex=?
姓名和性别同时存在的查询, 发送的语句和结果
查询条件
where 1=1 and name like concat('%', ?, '%') and sex=?
2.2 在 UPDATE 更新列中使用 if 标签
有时候我们不希望更新所有的字段, 只更新有变化的字段。
2.2.1 更新条件
只更新有变化的字段, 空值不更新。
2.2.1 动态 SQL
接口方法
/** * 更新非空属性 */ int updateByPrimaryKeySelective(Student record);
对应的 SQL
update student `name` = #{name,jdbcType=VARCHAR}, phone = #{phone,jdbcType=VARCHAR}, email = #{email,jdbcType=VARCHAR}, sex = #{sex,jdbcType=TINYINT}, locked = #{locked,jdbcType=TINYINT}, gmt_created = #{gmtCreated,jdbcType=TIMESTAMP}, gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, where student_id = #{studentId,jdbcType=INTEGER}
2.2.3 测试
@Test public void updateByStudentSelective() { SqlSession sqlSession = null; sqlSession = sqlSessionFactory.openSession(); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student student = new Student(); student.setStudentId(1); student.setName("明明"); student.setPhone("13838438888"); System.out.println(studentMapper.updateByPrimaryKeySelective(student)); sqlSession.commit(); sqlSession.close(); }
结果如下
2.3 在 INSERT 动态插入中使用 if 标签
我们插入数据库中的一条记录, 不是每一个字段都有值的, 而是动态变化的。在这时候使用 if 标签, 可帮我们解决这个问题。
2.3.1 插入条件
只有非空属性才插入。
2.3.2 动态SQL
接口方法
/** * 非空字段才进行插入 */ int insertSelective(Student record);
对应的SQL
insert into student
mybatis注解动态sql_超全MyBatis动态SQL详解相关推荐
- 上手Redis系列(六):超全Geospatial特殊类型详解(地理位置)
学习Redis之前,我还是觉得我务必跟你说一声,也是在我文章之中说的很多的一句话,我想也会适用于学习Redis,那就是在接触文章里的Reids命令时,不用试图去记这些命令 ,用到时去看API帮助文档即 ...
- 【超全】一文详解机器学习特征工程(附代码)
特征工程是使用专业背景知识和技巧处理数据,使得特征值(自变量)能在机器学习算法上发挥更好的作用的过程.python的sklearn库,对于特征工程的处理提供了强大的接口. 在本文中,我将详细介绍特征工 ...
- Mybatis注解开发(超详细)
Mybatis注解开发 mybatis的常用注解 使用 Mybatis 注解实现基本 CRUD 项目目录结构 编写实体类 使用注解方式开发持久层接口 编写 SqlMapConfig.xml 配置文件 ...
- python3d动态图-Python图像处理之gif动态图的解析与合成操作详解
本文实例讲述了Python图像处理之gif动态图的解析与合成操作.分享给大家供大家参考,具体如下: gif动态图是在现在已经司空见惯,朋友圈里也经常是一言不合就斗图.这里,就介绍下如何使用python ...
- c++定义一个动态全局变量_静态链接与动态链接的宏观概述及微观详解
静态链接与动态链接的宏观概述及微观详解 第一部分 宏观概述 1. 静态链接 静态链接就是在程序运行前,链接器通过对象文件中包含的重定位表,完成所有重定位操作,并最终形成一个在运行时不需要再次进行依赖库 ...
- python调用shell脚本的参数_使用python执行shell脚本 并动态传参 及subprocess的使用详解
最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 subpr ...
- iptable 详解_最全的iptables防火墙详解.pdf
最全的iptables防火墙详解 iptables / iptables / iippttaabblleess官方网站:hhttttpp::nneettffiilltteerr..oorrgg// • ...
- centos7中ps显示的内容_值得收藏,史上最全Linux ps命令详解
原标题:值得收藏,史上最全Linux ps命令详解 一.程序员的疑惑 大概在十多年前,我当时还是一个产品经理.由于一些工作的原因,需要向运维工程师学习一些linux常用命令. 当使用linux ps这 ...
- 猛兽之地服务器维护,猛兽之地Roguelands全材料获取途径详解
以下就是小编为大家带来的猛兽之地Roguelands全材料获取途径详解: 蘑菇镇主要产出: 发光蘑菇 屎壳螂 少量怪兽抓 古老废墟主要产出: 甲壳碎片 辛辣种子 星空岩 折磨大陆主要产出: 星之果 少 ...
最新文章
- 使用C++ ostringstream来格式化字符串输出
- Hibernate annotation多对多配置
- Attachment multiple read API - performance with regular expression
- 玩转 Rockchip 的开发板,这些信息你要知道
- c#中的long类型示例_C#中带示例的无符号字节数组
- java作业 景区门票
- 第一章 在VS2008下如何配置好CG环境
- python实践gcForest模型对鸢尾花数据集iris进行分类
- ubuntu安装 ssh server
- Delphi 德尔菲法
- 面试:MRO问题 (理解笔记)
- 灵魂 我·将·归·来·开·放
- Cortex-A7 MPCore 架构
- 元气骑士卡无限服务器,元气骑士养剑葫怎么卡无限飞剑bug方法介绍
- 前端调取.net core webapi 报错:“...CORS policy: Response to preflight request ...“的问题成因和解决办法。
- ctr 平滑_ctr平滑
- SpringBoot+Vue+Element-UI实现人事管理系统
- Unity | 总结:OCR文字识别、公式识别
- AUTOSAR实验七 PWM和呼吸灯
- USB标准协议下载地址