Mybatis 动态SQL – 使用choose标签动态生成条件语句

之前我们介绍了if,where标签的使用;本篇我们需要在if,where标签的基础上介绍如何使用Mybatis提供的choose标签动态生成条件语句。

如果您对if,where标签动态生成条件语句不太了解,建议您先进行了解后再阅读本篇,可以参考:

Mybatis 动态SQL – 使用if,where标签动态生成条件语句icon-default.png?t=N7T8https://blog.csdn.net/m1729339749/article/details/132627894

一、数据准备

这里我们直接使用脚本初始化数据库中的数据

-- 如果数据库不存在则创建数据库
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARSET utf8;
-- 切换数据库
USE demo;
-- 创建用户表
CREATE TABLE IF NOT EXISTS T_TEACHER(ID INT PRIMARY KEY COMMENT '教师编号',TEACHER_NAME VARCHAR(64) NOT NULL COMMENT '教师名称',DEPARTMENT VARCHAR(16) NOT NULL COMMENT '所属部门',BIRTH DATE NOT NULL COMMENT '出生年月',DEGREE VARCHAR(16) NOT NULL COMMENT '学历(ZK:专科, BK:本科, YJS:研究生, BS:博士)'
);
-- 插入用户数据
INSERT INTO T_TEACHER(ID, TEACHER_NAME, DEPARTMENT, BIRTH, DEGREE)
VALUES(1, '张三1', '001', '1990-06-12', 'BK'),(2, '李四1', '002', '1992-05-10', 'BK'),(3, '张三2', '003', '1988-01-15', 'YJS'),(4, '李四2', '001', '1979-03-10', 'BK'),(5, '李四3', '003', '1995-08-16', 'YJS');

创建了一个名称为demo的数据库;并在库里创建了名称为T_TEACHER的教师表并向表中插入了数据

二、环境搭建

1、创建实体类

在cn.horse.demo下创建TeacherInfo实体类:

TeacherInfo类:

package cn.horse.demo;import java.time.LocalDate;public class TeacherInfo {private Integer id;private String name;private String department;private LocalDate birth;private String degree;@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("{ ");stringBuilder.append("id: ");stringBuilder.append(this.id);stringBuilder.append(", ");stringBuilder.append("name: ");stringBuilder.append(this.name);stringBuilder.append(", ");stringBuilder.append("department: ");stringBuilder.append(this.department);stringBuilder.append(", ");stringBuilder.append("birth: ");stringBuilder.append(this.birth);stringBuilder.append(", ");stringBuilder.append("degree: ");stringBuilder.append(this.degree);stringBuilder.append(" }");return stringBuilder.toString();}
}

2、Mapper配置文件

在resources的目录下新建TeacherInfoMapper.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.horse.demo.TeacherInfoMapper"><select id="findAll" parameterType="cn.horse.demo.TeacherInfoQuery" resultType="cn.horse.demo.TeacherInfo">SELECTID,TEACHER_NAME name,DEPARTMENT,BIRTH,DEGREEFROM T_TEACHER<where><if test="null != id and '' != id">AND ID = #{id}</if><if test="null != name and '' != name">AND TEACHER_NAME = #{name}</if><if test="null != department and '' != department">AND DEPARTMENT = #{department}</if><if test="null != degree and '' != degree">AND DEGREE = #{degree}</if></where></select>
</mapper>

3、引入配置文件

在resources下新建mybatis-config.xml配置文件,并引入TeacherInfoMapper.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="logImpl" value="JDK_LOGGING"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="org.gjt.mm.mysql.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;useSSL=false&amp;characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value="horse"/></dataSource></environment></environments><mappers><mapper resource="demo/TeacherInfoMapper.xml" /></mappers>
</configuration>

4、会话工具类

在cn.horse.demo包下新建SqlSessionUtils工具类

package cn.horse.demo;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.InputStream;
import java.util.Objects;public class SqlSessionUtils {private static final SqlSessionFactory sqlSessionFactory;static {// 读取mybatis配置文件InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");// 根据配置创建SqlSession工厂sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}/*** 开启会话* @return*/public static SqlSession openSession() {return sqlSessionFactory.openSession();}/*** 关闭会话* @param sqlSession*/public static void closeSession(SqlSession sqlSession) {if(Objects.nonNull(sqlSession)) {sqlSession.close();}}
}

5、JDK 日志系统配置

在resources的目录下新建logging.properties配置文件

handlers=java.util.logging.ConsoleHandler
.level=INFOcn.horse.demo.TeacherInfoMapper.level=FINER
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tT.%1$tL %4$s %3$s - %5$s%6$s%n

在cn.horse.demo下新建JdkLogConfig类:

JdkLogConfig类:

package cn.horse.demo;import java.io.IOException;
import java.io.InputStream;
import java.util.logging.LogManager;public class JdkLogConfig {public JdkLogConfig() {try {InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("logging.properties");LogManager.getLogManager().readConfiguration(inputStream);} catch (IOException e) {throw new RuntimeException(e);}}
}

6、启动程序

package cn.horse.demo;import org.apache.ibatis.session.SqlSession;import java.util.List;public class Main {public static void main(String[] args) {// 引入JDK日志配置System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");TeacherInfoQuery teacherInfoQuery = new TeacherInfoQuery();teacherInfoQuery.setId(1);teacherInfoQuery.setName("张三1");teacherInfoQuery.setDepartment("001");teacherInfoQuery.setDegree("BK");findAll("cn.horse.demo.TeacherInfoMapper.findAll", teacherInfoQuery);}private static void findAll(String statement, TeacherInfoQuery teacherInfoQuery) {SqlSession sqlSession = null;try {sqlSession = SqlSessionUtils.openSession();List<TeacherInfo> teacherInfoList = sqlSession.selectList(statement, teacherInfoQuery);for (TeacherInfo teacherInfo: teacherInfoList) {System.out.println(teacherInfo);}} finally {SqlSessionUtils.closeSession(sqlSession);}}
}

执行后的结果如下:

三、choose标签的使用

在上面的运行结果中,我们可以看到执行的SQL语句:

SELECT ID, TEACHER_NAME name, DEPARTMENT, BIRTH, DEGREE FROM T_TEACHER WHERE ID = ? AND TEACHER_NAME = ? AND DEPARTMENT = ? AND DEGREE = ?

从SQL中我们可以看到条件语句中包含了ID、TEACHER_NAME、DEPARTMENT、DEGREE;而在实际的场景中ID是唯一的,ID作为条件时,其他的条件就显得比较多余,显然上面动态生成的条件语句是存在一些问题的,下面我们使用choose标签来解决此类问题:

<select id="findAll" parameterType="cn.horse.demo.TeacherInfoQuery" resultType="cn.horse.demo.TeacherInfo">SELECTID,TEACHER_NAME name,DEPARTMENT,BIRTH,DEGREEFROM T_TEACHER<where><choose><when test="null != id and '' != id">AND ID = #{id}</when><otherwise><if test="null != name and '' != name">AND TEACHER_NAME = #{name}</if><if test="null != department and '' != department">AND DEPARTMENT = #{department}</if><if test="null != degree and '' != degree">AND DEGREE = #{degree}</if></otherwise></choose></where>
</select>

choose标签:标签中可以包含多个when标签、一个otherwise标签

when标签:test属性值用作条件判断,与if标签的test属性一样;when标签可以多次使用

otherwise标签:otherwise标签最多只能使用一次,并且只能作为choose标签内的最后一个标签。

choose标签类似于Java中的switch语句,会依次判断when标签中的条件是否满足,直到找到满足条件的when标签,并将when标签中的条件语句拼装到SQL语句中并跳出choose标签;如果找不到满足条件的when标签,则将otherwise标签中的条件语句拼装到SQL语句中并跳出choose标签;

1、示例:使用ID查询教师

// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");TeacherInfoQuery teacherInfoQuery = new TeacherInfoQuery();
teacherInfoQuery.setId(1);
teacherInfoQuery.setName("张三1");
teacherInfoQuery.setDepartment("001");
teacherInfoQuery.setDegree("BK");
findAll("cn.horse.demo.TeacherInfoMapper.findAll", teacherInfoQuery);

执行后的结果如下:

结果分析:

choose标签中,先判断第一个when标签条件是否满足,因为id为1,第一个条件满足,则将条件AND ID = #{id} 拼装到SQL语句中并跳出choose标签;所以执行的条件语句中只有ID = ? 条件

2、示例:使用名称查询教师

// 引入JDK日志配置
System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");TeacherInfoQuery teacherInfoQuery = new TeacherInfoQuery();
teacherInfoQuery.setName("张三1");
findAll("cn.horse.demo.TeacherInfoMapper.findAll", teacherInfoQuery);

执行后的结果如下:

结果分析:

choose标签中,先判断第一个when标签条件是否满足,因为id为null,第一个条件不满足,没有找到满足条件的when标签,则将otherwise标签中的条件语句拼装到SQL语句中并跳出choose标签(由于这里otherwise标签中的条件语句是动态SQL语句,则会执行动态SQL语句,执行后的结果AND TEACHER_NAME = #{name} 作为otherwise标签的内容);所以执行的条件语句中只有TEACHER_NAME = ? 条件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/68156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS中如何实现文字描边效果(Text Stroke)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 文字描边效果&#xff08;Text Stroke&#xff09;⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个…

Go实现LogCollect:海量日志收集系统【上篇——LogAgent实现】

Go实现LogCollect&#xff1a;海量日志收集系统【上篇——LogAgent实现】 下篇&#xff1a;Go实现LogCollect&#xff1a;海量日志收集系统【下篇——开发LogTransfer】 项目架构图&#xff1a; 0 项目背景与方案选择 背景 当公司发展的越来越大&#xff0c;业务越来越复杂…

Mysql底层数据结构为什么选择B+树

索引底层采用什么数据结构&#xff0c;为什么使用B树而不是其他数据结构&#xff1a; &#xff08;1&#xff09;如果采用二叉树&#xff1a;使用递增字段作为索引时&#xff0c;二叉树会退化成链表&#xff0c;查找效率太低 &#xff08;2&#xff09;如果采用红黑树&#xf…

微信小程序开发:一种新型的移动应用程序开发方式

一、引言 随着移动互联网的快速发展&#xff0c;微信小程序作为一种新型的移动应用开发方式&#xff0c;正在受到越来越多的关注。微信小程序是一种基于微信平台的轻量化应用&#xff0c;开发者可以通过微信提供的开发工具和接口&#xff0c;开发出各种具有特定功能的应用程序…

如何创建一个自己的sphinx文档网站

文章目录 前言一、操作步骤1.安装anaconda2.启动python3.8环境3.安装Sphinx4.创建文件夹5.初始化环境6. 编译7.文件夹搭查看8.搭建nginx查看8. 更换主题9.错误修复10.这里提供两个模板1.Demo_md2.Demo_rst前言 最近看到公司的文档中心,突然想起,为什么不为自己创建一个文档中…

在k8s中用label控制Pod部署到指定的node上

案例-标注k8s-node1是配置了SSD的节点 kubectl label node k8s-node1 disktypessd 查看标记 测试 将pod部署到disktypessd的节点上&#xff08;这里设置了k8s-node1为ssd&#xff09; 部署后查看结果-副本全都运行在了k8s-node1上—符合预期 删除标记 kubectl label node k8…

顶尖211“小清华”!强过985,不要错过它!

一、学校及专业介绍 西安电子科技大学&#xff08;Xidian University&#xff09;&#xff0c;简称“西电” &#xff0c;位于陕西省西安市&#xff0c;是中央部属高校&#xff0c;直属于教育部&#xff0c;为全国重点大学&#xff0c;位列国家“双一流”“211工程”&#xff…

MySQL的内置函数复合查询内外连接

文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…

Vagrant命令

文章目录 1.介绍2.下载3. 配置3.1 配置环境变量3.2 在xshell中连接使用 4. 相关命令4.1 Box相关4.2 初始化环境4.4 虚拟机相关 1.介绍 Vagrant 是一个虚拟机管理工具 2.下载 https://www.vagrantup.com/ 3. 配置 3.1 配置环境变量 测试安装是否成功 3.2 在xshell中连接使…

码云使用记录

码云使用记录 主要步骤 1、https://gitee.com 注册 2、下载Git 3、配置SSH 4、创建远程仓库 5、切到本地项目目录下将本地项目推到远程 前两步根据提示进行即可&#xff0c;下面从第三步开始讲解 3、配置SSH&#xff08;用于提交代码和更新代码&#xff09; https://gitee.…

机器人中的数值优化(七)——修正阻尼牛顿法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

CCKS2023:基于企业数仓和大语言模型构建面向场景的智能应用

8月24日-27日&#xff0c;第十七届全国知识图谱与语义计算大会&#xff08;CCKS 2023&#xff09;在沈阳召开。大会以“知识图谱赋能通用AI”为主题&#xff0c;探讨知识图谱对通用AI技术的支撑能力&#xff0c;探索知识图谱在跨平台、跨领域等AI任务中的作用和应用途径。 作为…

nc前端合计行

nc前端合计行 1.无表体和单表体的合计行加法 只要卡片下 如果是只有表头要合计行就只留ShowTotalLine&#xff1b;如果是只有表体要合计行就只留ShowTotalLineTabcodes 2.多表体的合计行加法 表头卡片下和列表下都要 3.档案的合计行加法 重写一下列表模板

Python时间序列分析苹果股票数据:分解、平稳性检验、滤波器、滑动窗口平滑、移动平均、可视化...

全文链接&#xff1a;https://tecdat.cn/?p33550 时间序列是一系列按时间顺序排列的观测数据。数据序列可以是等间隔的&#xff0c;具有特定频率&#xff0c;也可以是不规则间隔的&#xff0c;比如电话通话记录&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。…

史上最全的计算机发展编年史!!!

今天分享给大家&#xff0c;以供参考。 1614年 苏格兰人约翰纳皮尔&#xff08;John Napier&#xff09;发表了一篇论文&#xff0c;其中提到他发明了一种可以计算四则运算和方根运算的精巧装置。 1623年 威廉契克卡德&#xff08;Wilhelm Schickard&#xff09;制作了一个通过…

Swift 周报 第三十六期

文章目录 前言新闻和社区消息称苹果公司和印度财政部官员磋商&#xff0c;扩大在印度的制造产能iPhone 15 Pro 机型新增泰坦灰iPhone 15 全系配 USB-C 苹果拒绝接口和安卓互通 提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组整理周报的第三十…

mysql-1:认识mysql

文章目录 数据库概述什么是数据库什么是关系型数据库 MySQL的概述MySQL是什么MySQL发展历程 SQL的概述什么是SQLSQL发展的简要历史&#xff1a;SQL语言分类 数据库概述 什么是数据库 数据库就是[存储数据的仓库]&#xff0c;其本质是一个[文件系统]&#xff0c;数据按照特定的…

生成式人工智能能否使数字孪生在能源和公用事业行业成为现实?

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 克服障碍&#xff0c;优化数字孪生优势 要实现数字孪生的优势&#xff0c;您需要数据和逻辑集成层以及基于角色的演示。如图 1 所示&#xff0c;在任何资产密集型行业&#xff08;如能源和公用事业&#xff09;中&…

cocosCreator2.4.x 打包 ios ,xcode问题记录

Q&#xff1a;Uncaught ReferenceError: CC_PHYSICS_BUILTIN is not defined A&#xff1a;先clean build folder....&#xff0c;然后重新build Q&#xff1a;xcode 使用模拟器预览 报错 In /Library/Developer/Xcode/DerivedData/hello_world-djnvsdcqyfoqvdepilidvunfunto…

vue2 封装通用表格数据筛选的重置摁钮

放弃冗余代码吧&#xff0c;封装个混入 封装逻辑 // 重置表格筛选参数 export const queryReset {methods: {queryReset(form, method "getData", fn) {if (!this[form]) {form "queryForm";}this.$data[form] this.$options.data()[form];this[form…