动态sql语句

news2024/11/23 11:07:13

1.1 动态sql语句概述

Mybatis 的映射文件中,业务逻辑复杂时, SQL是动态变化的,此时在前面的学习中 SQL 就不能满足要求了。

参考的官方文档:
在这里插入图片描述

1.2 动态 SQL 之<if>

根据实体类的不同取值,使用不同的 SQL语句来进行查询
比如在 id 如果不为空时可以根据id查询,如果username 不为空时还要加入用户名作为条件。
这种情况在多条件组合查询中经常会碰到

  <select id="findColl" parameterType="user" resultType="user">
        select * from T_user
        <where> <!--表示where-->
            <if test="id!=0">
                 id=#{id}
            </if>
            <if test="username!=null and username!=''">
                and username=#{username}
            </if>
        </where>

编写dao接口:

//多条件查询
public List<User> findColl(User user);

当查询条件id和username都存在时,控制台打印的sql语句如下:

     @Test
    public void findCollT(){
        SqlSession sqlSession = MybatisUtils.getSqlSession(true);
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user=new User();
        user.setId(1);
        user.setUsername("张三");
        List<User> coll = mapper.findColl(user);
        System.out.println(coll.toString());
        
        MybatisUtils.closeSqlSession(sqlSession);
    }

在这里插入图片描述

当查询条件只有id存在时,控制台打印的sql语句如下:

 //获得MyBatis框架生成的UserDao接口的实现类
@Test
    public void findCollT(){
        SqlSession sqlSession = MybatisUtils.getSqlSession(true);
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user=new User();
        user.setId(1);
        List<User> coll = mapper.findColl(user);
        System.out.println(coll.toString());MybatisUtils.closeSqlSession(sqlSession);
    }

在这里插入图片描述

总结语法:

<where>:条件标签。如果有动态条件,则使用该标签代替 where 关键字。
<if>:条件判断标签。
<if test=“条件判断”>
    查询条件拼接
</if>

1.3 动态sql之set (update insert)

  <!-- 动态语句 set 更新语句 update 表名 set name=#{name} -->
 <update id="updateMap" parameterType="map">
        update T_user 
        <set>
            <if test="username!=null">username=#{username},</if>
            <if test="sex!=null">sex=#{sex}</if>
        </set>
        <where>
            <if test="id!=null">id=#{id}</if>
        </where>
    </update>
    <!-- 动态语句 set 插入语句 insert into 表名 set name=#{name},age=#{age} -->
 
    <insert id="saveMap" parameterType="map">
        insert into T_user
        <set>
            <if test="id!=null">id=#{id},</if>
            <if test="username!=null">username=#{username},</if>
            <if test="sex!=null">sex=#{sex},</if>
            <if test="address!=null">address=#{address},</if>
            <if test="birthday!=null">birthday=#{birthday}</if>
        </set>
    </insert>

编写dao接口添加方法:

public int updateMap(Map<String ,Object> map);public int saveMap(Map<String ,Object> map);

测试类编写:

修改的测试方法
@Test
    public void updatemap(){
        SqlSession sqlSession = MybatisUtils.getSqlSession(true);
        UserDao mapper = sqlSession.getMapper(UserDao.class);Map<String,Object> map=new HashMap<>();
        map.put("id",1);
        map.put("username","老六");
        map.put("sex","女");
        int i = mapper.updateMap(map);
        System.out.println(i);
    }
添加的测试方法
    @Test
    public void savemapT(){
        SqlSession sqlSession = MybatisUtils.getSqlSession(true);
        UserDao mapper = sqlSession.getMapper(UserDao.class);Map<String,Object> map=new HashMap<>();
        map.put("username","老六");
        map.put("sex","女");
        map.put("address","郑州");
        map.put("birthday",Date.valueOf("2010-03-09"));
        int i = mapper.saveMap(map);
        System.out.println(i);
    }

总结语法:

<set>:条件标签。set 元素可以用于动态包含需要更新的列
<if>:条件判断标签。
<if test="条件判断">
    查询条件拼接
</if>

1.4 动态sql之choose (when, otherwise)

相当于Java中的switch语句

当when有条件满足的时候,就跳出choose

 <choose>
        <when test="条件1">...</when>
        <when test="条件2">...</when>
        <when test="条件3">...</when>
        <otherwise>其他条件</otherwise>
</choose>

代码演示步骤:

1、编写Dao接口代码

2、编写mapper文件

3、测试运行

代码实现:

编写Dao接口代码

public List<User> showUserfindAll(
       @Param("username") String username,
        @Param("sex") String sex,
        @Param("address") String address,
        @Param("birthday") Date birthday;

编写mapper文件

<!-- 动态语句choose when when otherwise -->
<!-- if elseif elseif else
    <choose>
        <when test=""></when>
        <when test=""></when>
        <when test=""></when>
        <otherwise>...</otherwise>
    </choose>-->
<select id="showUserfindAll" resultType="cn.zxy.pojo.User">
    select * from user where 
    <choose>
        <when test="username!=null and username!=''">
             username like concat("%",#{username},"%")
        </when>
        <when test="sex!=null and sex!=''">
             sex =#{sex}
        </when>
        <when test="address!=null and address!=''">
            address like concat("%",#{address},"%")
        </when>
        <otherwise>
             year(birthday)=year(#{birthday})
        </otherwise></choose>

另一种写法


 <select id="showUserfindAll" resultType="cn.zxy.pojo.User">
        select * from user 
	<where>
        <choose>
            <when test="username!=null">
              <choose>
                 <when test="username.indexOf('%')!=-1"> username like #{username}</when>
                 <when test="username.indexOf('_')!=-1">username like #{username}</when>
                 <otherwise>username = #{username}</otherwise>
              </choose>
            </when>
            <when test="sex!=null and sex!=''">
               sex =#{sex}
            </when>
            <when test="address!=null and address!=''">
                address like concat("%",#{address},"%")
            </when>
            <otherwise>
                birthday=#{birthday}
            </otherwise>
        </choose>
	</where>

    </select>

实体和数据库名字不匹配

<!-- 查询中如果表字段名和实体类名不一致,不想定义ResultMap,可以使用查询的列名 -->
<sql id="s1p">id,user_name username,birthday birth,address addr,sex sex</sql><select id="showUserfindAll" resultType="cn.zxy.pojo.User">
    select <include refid="s1p"/> from user where 1=1
    <choose>
        <when test="username!=null">
            <choose>
                <when test="username.indexOf('%')!=-1">user_name like #{username}</when>
                <when test="username.indexOf('_')!=-1">user_name like #{username}</when>
                <otherwise>user_name = #{username}</otherwise>
            </choose>
        </when>
        <when test="sex!=null and sex!=''">
            and sex =#{sex}
        </when>
        <when test="address!=null and address!=''">
            and address like concat("%",#{addr},"%")
        </when>
        <otherwise>
            and year(birthday)=year(#{birth})
        </otherwise>
    </choose>
</select>

测试运行

 @Test
    public void test() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        List<User> users = userDao.showUserfindAll("小_", "男", "河", null);
        System.out.println(users.toString());}

1.5 动态 SQL 之<foreach>

循环执行sql的拼接操作,例如:SELECT * FROM user WHERE id IN (1,2,5)。

foreach 迭代一个集合,通常用于in条件

属性:

  • item 查询条件

  • collection:必须指定

    • list

    • array

    • map—key

  • open : 括号 (

  • separator :分割符 ,

  • close :括号 )

例子如下

  <!--循环迭代-->
<select id="findByIds" parameterType="list" resultType="user">
    <!--
        collection: 表示集合存储类型 分别为 list array数组
           open : id in (  是指代  where id in(
           close: 闭合括号
           item : 查询条件
           separator: 分割符
    -->
    select * from T_user
    <where>
    <foreach collection="list" open="id in (" close=")" item="id" separator=",">
        #{id}
    </foreach>
    </where>
</select>

编写dao接口:

//根据多个id查询
public List<User> findByIds(List<Integer> ids);

测试代码片段如下:

 @Test
    public void findByidst() {
        //获取sqlssession给定的对象
        SqlSession sqlSession = MybatisUtils.getSqlSession(true);
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        //创建list集合 并赋值
        List<Integer> list=new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        //把集合里面的值赋给mapper
        List<User> byIds = mapper.findByIds(list);
        for (User byId : byIds) {
            System.out.println(byId);
        }
        MybatisUtils.closeSqlSession(sqlSession);
    }

批量插入:

Mapper接口编写

public  void insert(List<User> list);

映射文件编写:

 <insert id="insert" parameterType="user">
        insert into user values
        <foreach collection="list" separator="," item="user">
            (#{user.id},#{user.username},#{user.sex},#{user.address},#{user.birthday})
        </foreach>
    </insert>

测试类编写:

 @Test
    public void inTest(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession(true);
        DUserMapper mapper = sqlSession.getMapper(DUserMapper.class);
        long start=System.currentTimeMillis();
        log.info("开始的时间{}",start);
        List<User> userList=new ArrayList<>();
        User user;
        for (int i = 0; i < 5; i++) {
            user=new User();
            user.setUsername("唐"+i);
            user.setSex("男");
            user.setAddress("河南北京");
            user.setBirthday(new Date());
            userList.add(user);
        }
        mapper.insert(userList);
        long end = System.currentTimeMillis();
        log.info("结束的时间{}",(end-start));
    }

总结语法:

<foreach>:循环遍历标签。适用于多个参数或者的关系。
    <foreach collection="" open="" close="" item="" separator="">
        获取参数
    </foreach>

属性
collection:参数容器类型, (list-集合, array-数组)
open:开始的 SQL 语句 id in (
close:结束的 SQL 语句
item:参数变量名
separator:分隔符

1.6 SQL片段抽取

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

<!--抽取sql片段简化编写-->
<sql id="selectUser" select * from student</sql>
<!--根据id查询-->
<select id="findById" parameterType="int" resultType="user">
    <include refid="selectUser"></include> where id=#{id}
</select>
<!--根据ids遍历-->
<select id="findByIds" parameterType="list" resultType="student">
    <include refid="selectUser"></include>
    <where>
        <foreach collection="array" open="id in(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </where>
</select>

总结语法:

我们可以将一些重复性的 SQL 语句进行抽取,以达到复用的效果。

-  <sql>:抽取 SQL 语句标签。 
-  <include>:引入 SQL 片段标签。 
   <sql id=“片段唯一标识”>抽取的 SQL 语句</sql> 
<include refid=“片段唯一标识”/>
 

1.7 知识小结

MyBatis映射文件配置:

<select>:查询
​
<insert>:插入
​
<update>:修改
​
<delete>:删除
​
<where>:where条件
​
<if>:if判断
​
<foreach>:循环
​
<sql>:sql片段抽取
​

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

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

相关文章

常见安装工具以及命令(工作常用)长期维护

dockermongodbnginxredis 1.docker 启动2.docker 安装 MongoDB3.启动nginx4.redis配置&#xff0b;安装4.1 Redis的启动和停止4.2 后台启动方式 systemctl start docker redis-server /root/myredis/redis.conf docker start mymongo docker exec -it mymongo /bin/bash 1.doc…

代码随想录算法训练营第58天 | 单调栈 ●739 每日温度 ●496下一个更大元素I ●503下一个更大元素II ●42 接雨水 ●84 柱形图中最大的矩形

#单调栈&#xff1a; 单调栈就是保持栈内元素有序。和栈与队列&#xff08;239. 滑动窗口最大值 自己写一个class来实现单调队列&#xff09;一样&#xff0c;需要我们自己维持顺序&#xff0c;没有现成的容器可以用。 通常是一维数组&#xff0c;要寻找任一个元素的右边或者…

浅谈物联网工程专业:技术融合与未来发展

技术融合与未来发展 引言1. 专业的定义与概述2. 专业的知识体系3. 专业的实践应用4. 专业的发展趋势5. 专业的就业前景结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收…

zabbix 企业级级监控(1) 监控自己

重点一 Zabbix简介在企业网络运维过程中&#xff0c;管理员必须随时关注各服务器和网络的运行状况&#xff0c;以便及时发现问题&#xff0c;尽可能减少故障的发生。当网络中的设备&#xff0c;服务器等数量较多时&#xff0c;为了更加方便&#xff0c;快捷的获得监控信息&…

【软件测试面试】腾讯数据平台笔试题-接口-自动化-数据库

数据库题 答案&#xff1a; Python编程题 答案&#xff1a; 接口参数化题 答案&#xff1a; 接口自动化题 答案&#xff1a; 以下是我收集到的比较好的学习教程资源&#xff0c;虽然不是什么很值钱的东西&#xff0c;如果你刚好需要&#xff0c;可以评论区&#…

6.3.6 利用Wireshark进行协议分析(六)----网页提取过程的协议分析

6.3.6 利用Wireshark进行协议分析&#xff08;六&#xff09;----网页提取过程的协议分析 利用Wireshark捕获网页访问过程中产生的应用协议报文&#xff0c;还原Web服务中报文的交互过程&#xff0c;为了防止网页直接从本地缓存中获取&#xff0c;我们首先需要清空浏览器保存的…

GO语言GMP模型

目录 程序入口 协程主动让出: 被动让出: schedule 监控线程 程序入口 在执行一系列检查和初始化&#xff08;创建多少个P&#xff0c;与M&#xff10;关联&#xff09;后&#xff0c;进入runtime.main,创建main goroutine,执行mian.mian。 一开始GO语言的调度只有M和G。每个M…

【代码随想录 | Leetcode | 第七天】链表 | 链表相交 | 环形链表 II

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来链表相交和环形链表 II的分享✨ 目录 前言面试题 02.07. 链表相交142. 环形链表 II总结 面试题 02.07. 链表相交 ✨题目链接点这里 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找…

C/C++ new A与new A()的区别

在C中&#xff0c;POD是“Plain Old Data”的缩写&#xff0c;即“普通旧数据”。POD data是指一种特殊类型的数据结构&#xff0c;它们具有简单的内存布局&#xff0c;没有构造函数、虚函数、私有/保护非静态数据成员&#xff0c;也没有虚继承等特性。这些数据结构可以直接通过…

k8s与集群管理

从docker讲起 终于有人把 Docker 讲清楚了&#xff0c;万字详解&#xff01; Docker资源&#xff08;CPU/内存/磁盘IO/GPU&#xff09;限制与分配指南 默认情况下&#xff0c;Docker容器是没有资源限制的&#xff0c;它会尽可能地使用宿主机能够分配给它的资源。如果不对容器资…

C++--day3(内联函数、结构体、类、封装、this、构造函数、析构函数)

#include <iostream>using namespace std;class My_stack { private:int *ptr; //指向堆区空间int top; //记录栈顶元素int size; public://有参构造My_stack(int size):ptr(new int[size]),top(-1){this->sizesize;cout<<"My_stack::有参构造&…

基于STM32的智能喂养系统

基于STM32的智能喂养系统 系统简介 自动检测环境温湿度&#xff0c;当温湿度低于阈值时自动打开加湿器&#xff1b;自动检测水位&#xff0c;当水位低于阈值时自动加水&#xff1b;自动检测有害气体&#xff0c;当检测到有害气体时自动打开风扇&#xff1b;同步状态到微信小程…

中间件上云部署 zookeeper

中间件上云部署 zookeeper 企业级中间件上云部署 zookeeper一、环境说明二、zookeeper部署YAML资源清单准备三、zookeeper部署及部署验证四、zookeeper应用验证 企业级中间件上云部署 zookeeper 一、环境说明 storageclassingress 二、zookeeper部署YAML资源清单准备 # vim…

图解java.util.concurrent并发包源码系列,原子类、CAS、AtomicLong、AtomicStampedReference一套带走

图解java.util.concurrent并发包源码系列&#xff0c;原子类、CAS、AtomicLong、AtomicStampedReference一套带走 原子类为什么要使用原子类CAS AtomicLong源码解析AtomicLong的问题ABA问题AtomicStampedReference 高并发情况下大量的CAS失败&#xff0c;导致CPU空转 往期文章&…

百度智能汽车负责人储瑞松离职,智驾重心转向ANP3

作者 | 王博 HiEV从多个信息源获悉&#xff0c;百度集团副总裁、百度智能汽车事业部总经理储瑞松将从百度离职。一位知情人士透露&#xff0c;储瑞松「即将启程&#xff0c;返回美国」。 继百度Apollo技术骨干郭阳离职后&#xff0c;储瑞松的变动&#xff0c;更加直白地反映出百…

电动汽车高压测试方案

针对电动汽车道路试验的要求&#xff0c;风丘科技携手德国IPETRONIK共同推出了电动汽车高压测试方案。电动汽车测试通常有两种测量手段&#xff1a;第一种是测量模拟量信号&#xff0c;包括电压、电流、温度和高压&#xff1b;第二种是使用数据记录仪或CAN卡从车辆总线读取数据…

你一定要收好这个系统性能测试用例模板

引言 文档目的 [简述本文档的目的] 适用范围 [指明本文档的适用范围和读者对象。如本测试计划是在策略和方法的高度说明如何计划、组织和管理测试项目。测试计划应包含足够的信息&#xff0c;使测试人员明白项目需要做什么、是如何运作的。另外&#xff0c;测试计划只是测试的…

刚体运动学-速度和加速度的表示方法(连体坐标系和世界坐标系)

0. 符号定义 自己画了一个图 下标 b b b是连体坐标系原点 O b O_b Ob​相对世界坐标系原点 O p O_p Op​的矢量在世界坐标系下的表示。下标 p p p是观察点相对世界坐标系原点 O p O_p Op​的矢量在世界坐标系下的表示。下标 p / b p/b p/b是观察点相对连体坐标系原点 O b O_b…

Python实现将pdf,docx,xls,doc,wps,zip,xlsx,ofd链接下载并将文件保存到本地

前言 本文是该专栏的第31篇,后面会持续分享python的各种干货知识,值得关注。 在工作上,尤其是在处理爬虫项目中,会遇到这样的需求。访问某个网页或者在采集某个页面的时候,正文部分含有docx,或pdf,或xls,或doc,或wps,或ofd,或xlsx,或zip等链接。需要你使用python自…

Yalmip入门教程(2)-变量定义和操作

博客中所有内容均来源于自己学习过程中积累的经验以及对yalmip官方文档的翻译&#xff1a;https://yalmip.github.io/tutorials/ 1.决策变量的定义 1.1 sdpvar 上文简单介绍了sdpvar函数的用法&#xff0c;接下来将对其进行详细介绍。复习一下&#xff0c;sdpvar函数的基本语…