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.hqwc.cn/news/98677.html

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

相关文章

uniapp从零到一的学习商城实战

涵盖的功能&#xff1a; 安装开发工具HBuilder&#xff1a;HBuilderX-高效极客技巧 创建项目步骤&#xff1a; 1.右键-项目&#xff1a; 2.选择vue2和默认模板&#xff1a; 3.完整的项目目录&#xff1a; 微信开发者工具调试&#xff1a; 1.安装微信开发者工具 2.打开…

MySQL访问和配置

目录 1.使用MySQL自带的客户端工具访问 2.使用DOS访问(命令行窗口WinR → cmd) 3.连接工具&#xff08;SQLyog或其它&#xff09; MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 1.使用MySQL自…

行测图形推理规律(一)元素组成

题库&#xff1a;粉笔网题库 (fenbi.com) 不知道和测评的行测题库是不是一样的&#xff0c;但是总结的规律应该是一样的。 规律并不唯一&#xff0c;题库的答案也只是参考答案&#xff0c;切勿当杠精&#xff0c;你觉得你的规律更合适就别管。本人所归纳的规律仅代表本人想法…

23. 带旋转的数独游戏

题目 Description 数独是一个基于逻辑的组合数字放置拼图&#xff0c;在世界各地都很受欢迎。 在这个问题上&#xff0c;让我们关注 网格的拼图&#xff0c;其中包含 个区域。 目标是用十六进制数字填充整个网格&#xff0c;即 &#xff0c;以便每列&#xff0c;每行和每个区…

electron win系统通知修改通知标题栏

标题栏的 electron.app.Electron 如何修改&#xff1a; var package require("../package.json"); app.setAppUserModelId(package.description); app.setAppUserModelId 在主进程的app这里修改

Vue组件之间进行传值的两种方式

在 Vue 中&#xff0c;组件之间传值是一个常见的操作&#xff0c;通常有两种方式来传递数据&#xff1a;props 和事件&#xff08;Event Bus&#xff09;。下面我将详细介绍这两种方式。 1. 通过 Props 传递数据 Props 是一种用于从父组件向子组件传递数据的方式。在子组件中…

低代码平台:IVX 重新定义编程

目录 &#x1f36c;一、写在前面 &#x1f36c;二、低代码平台是什么 &#x1f36c;三、为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f; &#x1f36d;1、不安全&#xff08;锁定特性&#xff09; &#x1f36d;2、不信任 &#x1f36c;四、IVX低代码平台 &a…

混合查询多家快递,快速掌握物流信息

在现代社会&#xff0c;快递服务已成为我们日常生活的重要组成部分。无论是购物还是文件传递&#xff0c;我们都需要快递服务的帮助。然而&#xff0c;不同的快递公司需要不同的查询方法&#xff0c;这无疑增加了我们的查询难度。因此&#xff0c;有没有一种方法可以让我们一次…

2023开学礼中国海洋大学《乡村振兴战略下传统村落文化旅游设计》许少辉新海洋图书馆

2023开学礼中国海洋大学《乡村振兴战略下传统村落文化旅游设计》许少辉新海洋图书馆

开启Clash和系统代理后Chrome无法打开网页但Edge正常

今天早上打开电脑准备摸鱼&#xff0c;发现Chrome打不开网页了。检查Clash正常&#xff0c;切换了节点&#xff0c;依然不行。关闭系统的代理可以解决。不然只提示ERR_TIMED_OUT。 各种研究配置&#xff0c;然后发现Edge却又不受影响。 通过火绒发现Chrome是有连接到7890端口的…

Prompt Tuning训练过程

目录 0. 入门 0.1. NLP发展的四个阶段&#xff1a; Prompt工程如此强大&#xff0c;我们还需要模型训练吗&#xff1f; - 知乎 Prompt learning系列之prompt engineering(二) 离散型prompt自动构建 Prompt learning系列之训练策略篇 - 知乎 ptuning v2 的 chatglm垂直领域训练记…

【2023集创赛】国家集创中心杯三等奖:不对称轻失配运算放大器

本文为2023年第七届全国大学生集成电路创新创业大赛&#xff08;“集创赛”&#xff09;国家集创中心杯三等奖作品分享&#xff0c;参加极术社区的【有奖征集】分享你的2023集创赛作品&#xff0c;秀出作品风采&#xff0c;分享2023集创赛作品扩大影响力&#xff0c;更有丰富电…