Mybatis动态SQL查询 --(附实战案例--8888个字--88质量分)

news2024/10/5 17:19:19

目录

前言

一、动态SQL---if标签

1. 持久层添加用户通用查询方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

二、动态SQL---where标签

1. 映射文件添加相关标签

2. 测试类新建测试方法

3. 运行结果

三、动态SQL---set标签

1. 持久层添加用户更新方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

四、动态SQL---choose和wen和otherwise标签

1. 持久层添加用户通用查询方法

2. 映射文件添加相关标签

3. 测试类新建测试方法

4. 运行结果

五、动态SQL---foreach标签

1. 遍历数组

(1)持久层添加用户批量删除方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

2. 遍历List

(1)持久层添加用户批量增加方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

3. 遍历Map

(1)持久层添加多条件查询方法

(2)映射文件添加相关标签

(3)测试类新建测试方法

(4)运行结果

后言----查错


前言

        由于这是动态SQL,和先前得有些不一样,这里我们新建一个持久层接口UserMapper2和Mybatis映射文件UserMapper2.xml,测试类TestUserMapper2

 持久层接口UserMapper2

package com.mybatisstudy.mapper;

import com.mybatisstudy.pojo.User;

public interface UserMapper2 {
    
}

 Mybatis映射文件UserMapper2.xml

<?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 namespace="com.mybatisstudy.mapper.UserMapper2">
</mapper>

 测试类TestUserMapper2

import com.mybatisstudy.mapper.UserMapper2;
import com.mybatisstudy.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

public class TestUserMapper2 {
    InputStream is = null;
    SqlSession session = null;
    UserMapper2 userMapper2 = null;

    //前置方法,不必重复代码
    @Before
    public void before() throws Exception {
        System.out.println("前置方法执行·············");
        // (1)读取核心配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // (2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        // (4)SqlSessionFactory对象获取SqlSession对象
        session = factory.openSession();
        // (5)SqlSession对象获取代理对象
        userMapper2 = session.getMapper(UserMapper2.class);
    }

    //后置方法,释放资源
    @After
    public void after() throws Exception {
        System.out.println("后置方法执行·············");
        session.close();
        is.close();
    }
}

一、动态SQL---if标签

        一个查询的方法的Sql语句不一定是固定的。比如电商网站的查询商品,用户使用不同条件查询,Sql语句就会添加不同的查询条件。此时就需要在方法中使用动态Sql语句。

        <if> 标签内的Sql片段在满足条件后才会添加,用法为: <if test="条件"> 。例如:根据不同条件查询用户:

1. 持久层添加用户通用查询方法

// 用户通用查询
    List<User> findByCondition(User user);

2. 映射文件添加相关标签

<!-- 动态_if -->
    <select id="findByCondition" parameterType="com.mybatisstudy.pojo.User" resultType="com.mybatisstudy.pojo.User">
        select * from user where 1 = 1
        <if test="username != null and username.length()!=0">
            and username like #{username}
        </if>
        <if test="sex != null and sex.length() != 0">
            and sex = #{sex}
        </if>
        <if test="address != null and address.length() != 0">
            and address = #{address}
        </if>
    </select>

        这里肯定就会有读者会问 where 后面为什么要加1 = 1,因为单单使用if标签的话,第一个条件是不用 and 关键字的,而后续的条件是需要加 and 关键字的。但是用户添加条件是随机的,没办法判断哪一个是第一个条件,因此在这里先添加1 = 1,就无需考虑后续的条件是否是第一个条件啦,但是后面还有更好的办法解决这个问题,在这里只是可以用这个方法解决目前的问题。

3. 测试类新建测试方法

// 测试通用查询方法
    @Test
    public void testFindByCondition(){
        User user = new User();

        System.out.println("----------没有限制条件查询---------");
        List<User> users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);

        System.out.println("----------用户名带有name限制条件查询---------");
        user.setUsername("%name%");
        List<User> users1 = userMapper2.findByCondition(user);
        users1.forEach(System.out::println);

        System.out.println("----------姓名带有name和性别是man限制条件查询---------");
        user.setSex("woman");
        List<User> users3 = userMapper2.findByCondition(user);
        users3.forEach(System.out::println);
    }

4. 运行结果

  1. if中的条件不能使用&&/||,而应该使用and/or

  2. if中的条件可以直接通过属性名获取参数POJO的属性值,并且该值可以调用方法。 

二、动态SQL---where标签

OK,上述的问题的彩蛋来了,就是这个where标签,

<where> 可以代替sql中的where 1=1 和第一个and,更符合程序员的开发习惯,使用 <where> 后的映射文件如下:

1. 映射文件添加相关标签

<!-- 动态_if用where -->
    <select id="findByCondition" resultType="User" parameterType="User">
        select * from user
        <where>
            <if test="username != null and username.length()!=0">
                username like #{username}
            </if>
            <if test="sex != null and sex.length() != 0">
                and sex = #{sex}
            </if>
            <if test="address != null and address.length() != 0">
                and address = #{address}
            </if>
        </where>
    </select>

2. 测试类新建测试方法

这里不用新增,直接测试即可

3. 运行结果

因此我们以后就不用添加那个什么1 = 1了 

三、动态SQL---set标签

        <set> 标签用在update语句中。借助 <if> ,可以只对有具体值的字段进行更新。 <set> 会自动添加set关键字,并去掉最后一个if语句中多余的逗号。

1. 持久层添加用户更新方法

// 更新用户
    void update(User user);

2. 映射文件添加相关标签

<!-- 动态_set 更新用户 -->
    <update id="update" parameterType="User">
        update user
        <set>
            <if test="username != null and username.length()!=0">
                username = #{username}
            </if>
            <if test="sex != null and sex.length() != 0">
                and sex = #{sex}
            </if>
            <if test="address != null and address.length() != 0">
                and address = #{address}
            </if>
        </set>
        <where>
            id = #{id}
        </where>
    </update>

3. 测试类新建测试方法

// 测试更新用户方法
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(4);
        user.setUsername("man4");
        userMapper2.update(user);

        session.commit();
    }

4. 运行结果

        这里想整一个效果图,但是没想到帧率不够,最后居然绿屏了,但是不影响我们继续学习哈哈哈,理解到位即可害嗨嗨

四、动态SQL---choose和wen和otherwise标签

        这些标签表示多条件分支,类似JAVA中的 switch...case <choose> 类似switch <when> 类似 case <otherwise> 类似 default ,用法如下:

1. 持久层添加用户通用查询方法

这里就沿用那个通用查询方法即可

2. 映射文件添加相关标签

    <select id="findByCondition" resultType="User" parameterType="user">
        select * from user
        <where>
            <choose>
                <when test="username.length() &lt; 5">
                    username like #{username}
                </when>
                <when test="username.length() &lt; 10">
                    username = #{username}
                </when>
                <otherwise>
                    id = 1
                </otherwise>
            </choose>
        </where>
    </select>

        这段代码的含义就是当用户名的长度小于(不等于)5的时候,使用模糊查询,查询返回的是泛型为USer的List集合对象,list长度不定;当用户名大于等于5,小于10的时候,使用精确查询,查询指定用户名的用户,返回的是泛型为USer的List集合对象,list长度为1或者0;当用户名长度大于等于10的时候,返回的是id为1的用户

3. 测试类新建测试方法

// 测试通用查询方法——用户名
    @Test
    public void testFindByCondition1(){
        User user = new User();
        System.out.println("------------设用户名字长度为2------------");
        user.setUsername("%on%");
        List<User> users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);
        System.out.println("------------设用户名字长度为5------------");
        user.setUsername("%lions%");
        users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);

        System.out.println("------------设用户名字长度为9------------");
        user.setUsername("T_no_name");
        users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);

        System.out.println("------------设用户名字长度为10------------");
        user.setUsername("dddddddddd");
        users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);

        System.out.println("------------设用户名字长度为12------------");
        user.setUsername("programmer_1");
        users = userMapper2.findByCondition(user);
        users.forEach(System.out::println);
    }

4. 运行结果

        OK,其实从结果集和运行的SQL语句我们都可以得出,该映射文件的标签确实是验证了咱们刚刚的说法 

五、动态SQL---foreach标签

<foreach> 类似JAVA中的for循环,可以遍历集合或数组。 <foreach> 有如

下属性:

  1. collection:遍历的对象类型
  2. open:开始的sql语句
  3. close:结束的sql语句
  4. separator:遍历每项间的分隔符
  5. item:表示本次遍历获取的元素,遍历ListSet、数组时表示每项元素,遍历map时表示键值对的值。
  6. index:遍历List、数组时表示遍历的索引,遍历map时表示键值对的键。

1. 遍历数组

(1)持久层添加用户批量删除方法

// 用户批量删除
    void deleteBatch(int[] ids);

(2)映射文件添加相关标签

<!-- 批量删除 遍历数组-->    
    <delete id="deleteBatch" parameterType="int">
        delete from user
        <where>
            <foreach collection="array" item="id" open="id in(" close=")" separator=",">
                #{id}
            </foreach>
        </where>
    </delete>

其实这里对应的SQL语句就是:

delete from user in (?,?,?,...) 

(3)测试类新建测试方法

// 测试用户批量删除方法
    @Test
    public void testDeleteBatch(){
        int[] ids = {4,8};
        userMapper2.deleteBatch(ids);

        session.commit();
    }

(4)运行结果

运行前和运行后进行对比

 

 运行后,四和八对应的记录确实是被删除了

2. 遍历List

        <foreach> 遍历ListSet的方法是一样的,我们使用 <foreach> 遍历List进行批量添加。

(1)持久层添加用户批量增加方法

// 批量增加用户
    void insertBatch(List<User> users);

(2)映射文件添加相关标签

<!-- 批量增加用户 -->
    <insert id="insertBatch" parameterType="User">
        insert into user values
        <foreach collection="list" item="user" separator=",">
            (null,#{user.username},#{user.sex},#{user.address})
        </foreach>
    </insert>

        这里对应的SQL语句则是:

        insert into user values(null,username,sex,address)*N

        N可以为大于或等于1的数

        其中肯定会有人问到了,为什么id要为null,其实这里id是主键,我们建库建表的时候就已经设置了这里是自增字段,因此我们无需重复操作,如果设置有和表里面的id重复,说不定还会报错 

(3)测试类新建测试方法

// 测试批量增加用户方法
    @Test
    public void testInsertBatch(){
        List<User> list = new ArrayList<>();
        list.add(new User("man1","man","Beijing"));
        list.add(new User("man1","man","Beijing"));
        list.add(new User("man1","man","Beijing"));
        list.add(new User("man1","man","Beijing"));
        list.add(new User("man1","man","Beijing"));
        list.add(new User("man1","man","Beijing"));

        userMapper2.insertBatch(list);
        session.commit();
    }

(4)运行结果

运行前和运行后进行对比

 

        OK,通过对比,确实是增加了相关记录,这里的id是因为我测试过很多次了,所以比较大,大家不用在意这些哈哈哈,侧面反映我是很认真在写的,期待小伙伴的支持

3. 遍历Map

        下面我们使用 <foreach> 遍历Map进行多条件查询。

(1)持久层添加多条件查询方法

/**
     * 多条件查询
     * @param map 查询的键值对 键:属性名 值:属性值
     * @return
     */
    List<User> findUser(@Param("queryMap") Map<String,Object> map);

(2)映射文件添加相关标签

<!-- 多条件查询 遍历map-->
    <select id="findUser" parameterType="map" resultType="User">
        select * from user
        <where>
            <foreach collection="queryMap" separator="and" index="key" item="value">
                ${key} = #{value}
            </foreach>
        </where>
    </select>

这里对应的代码段其实就是:

select * from user where (? = ?) and (? = ?)

就像我们在淘宝,拼多多和京东上买东西使用筛选一样 

(3)测试类新建测试方法

// 测试多条件查询方法
    @Test
    public void testFindUser(){
        Map<String,Object> map = new HashMap<>();
        // 这里筛选性别为man和地址为Beijing的结果集
        map.put("sex","man");
        map.put("address","Beijing");
        List<User> users = userMapper2.findUser(map);
        users.forEach(System.out::println);
        // 再测试一下
        map.clear();
        // 这里筛选地址为Beijing和用户名为man1的结果集
        map.put("address","Beijing");
        map.put("username","man1");
        users = userMapper2.findUser(map);
        users.forEach(System.out::println);
    }

(4)运行结果

先看用户表数据

执行方法,观察结果是否一致 (是的,确实一致),不一致怎么会放出来呢

 

        OK,这里确实保持一致,动态查询就学到这里了,后续会继续更新相关内容滴,敬请关注! !!

后言----查错

        如果执行过程中有错误的话,不妨看看有没有导错包和导错类,下面就是上面用到相关的类用到的导包

持久层接口用到的包 

package com.mybatisstudy.mapper;

import com.mybatisstudy.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

测试类用到的包

import com.mybatisstudy.mapper.UserMapper2;
import com.mybatisstudy.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

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

相关文章

DNS域名协议(IP段获取DNS服务器、反解析获取主机域名、查找子域名记录、查看子域名记录)

IP段获取DNS服务器 nmap 192.168.190.0/24 -p53 反解析获取主机域名 host 192.168.137.149 192.168.137.149 查找子域名记录 dig 192.168.137.149 -t axfr MAILMAN.com 查看子域名记录 dig 192.168.137.149 -t axfr _msdcs.MAILMAN.com

神经微分方程Resnet变体实现内存下降和保持精度

本文内容&#xff1a; 1、学习神经微分方程的笔记&#xff0c;主要锻炼自己学习新知识的能力和看有很多数学原理的论文能力&#xff1b; 2、神经微分方程可以用于时序数据建模、动力学建模等&#xff0c;但是本文专注于分类问题-resnet变体<比较容易理解>&#xff1b; …

StringBuffer,StringBuilder,

StringBuffer 结构示意图&#xff0c; Serializable,可以实现网络传输 package com.jshedu.StringBuffer_;/*** author Mr.jia* version 1.0*/public class StringBuffer01 {public static void main(String[] args) {/*1.在父类中AbstractStringBuilder 属性char[] value不是f…

博弈论在电动车和电网系统中分布式模型预测控制研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Android中使用有趣的指示器和过渡自定义 Compose Pager

Android使用有趣的指示器和过渡自定义 Compose Pager google最近在compose中新增了Pager控件&#xff0c;HorizontalPager和VerticalPager。 页面之间的转换 该文档涵盖了访问页面从“对齐”位置滚动到多远的基础知识。我们可以使用这些信息来创建页面之间的过渡效果。 例…

DC:4通关详解

信息收集 漏洞发现 访问web 尝试弱口令 账号admin 可以执行ls du df看看发的包,我们是否有机会执行任意命令 发现post传参radio处可以任意命令执行 弹个shell先 提权 从vps上下载LinEnum.sh来枚举脆弱性 优化shell 现在shell就有自动补齐了 在/home/jim下发现密码字典…

cube-studio AI平台 提供开源模型示例列表(3月份)

文章目录背景AI应用商店背景 cube是腾讯音乐开源的一站式云原生机器学习平台&#xff0c;目前主要包含 1、数据管理&#xff1a;特征存储、在线和离线特征&#xff1b;数据集管理、结构数据和媒体数据、数据标签平台 2、开发&#xff1a;notebook(vscode/jupyter)&#xff1b…

【PTA天梯赛】L1-001 L1-002 L1-003 L-004 L-005 L-006 L-007 L-008 L-009 L1-010 c++

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;狠狠的刷题&#xff01;&#xff01;&#xff01;&#x1f308; 若有帮助&#xff0c;还请…

【Ubuntu 22.04 上配置 FTP 服务器步骤】

Ubuntu 22.04 上配置 FTP 服务器步骤 1.安装 vsftpd 软件包&#xff1a; sudo apt-get update sudo apt-get install vsftpd 2.查看vsftpd版本和状态&#xff0c;确认vsftpd安装成功和正常启动 2.修改 vsftpd 配置文件&#xff1a; sudo nano /etc/vsftpd.conf 3.在配置文件中…

Ethercat概念学习

Ethercat技术调研 背景 最近我们要基于Ethercat技术进行开发&#xff0c;首先需要了解其基本原理&#xff0c;github上看到了有相关实现&#xff0c;一起来看看吧。 Ethercat技术 速度更快 传输速率:2*100 Mbaud 全双工 高速性、高实时性 微秒级 像火车一样有帧头、帧尾&a…

如何对农田温室气体进行有效模拟?

农业是甲烷&#xff08;CH4&#xff09;、氧化亚氮&#xff08;N2O&#xff09;和二氧化碳&#xff08;CO2&#xff09;等温室气体的主要排放源&#xff0c;占全产业排放的13.5%。农田温室气体又以施肥产生的N2O和稻田生产产生的CH4为主&#xff0c;如何对农田温室气体进行有效…

计算机组成原理(四)输入/输出系统

一、概述 1.1前言 I/O设备是计算机组成原理之硬件最后的一部分。输入输出系统是计算机系统当中种类最多、功能最多、结构最复杂、构成也最多样的系统。在现代计算机系统当中&#xff0c;外部设备的总成本可以占到计算机总成本的80%以上。可以说&#xff0c;没有这些丰富多彩的外…

「Vue面试题」Vue项目中有封装过axios吗?主要是封装哪方面的?

一、axios是什么 axios 是一个轻量的 HTTP客户端 基于 XMLHttpRequest 服务来执行 HTTP 请求&#xff0c;支持丰富的配置&#xff0c;支持 Promise&#xff0c;支持浏览器端和 Node.js 端。自Vue2.0起&#xff0c;尤大宣布取消对 vue-resource 的官方推荐&#xff0c;转而推荐…

(原创)Flutter基础入门:实现各种Shape效果

前言 上一篇博客讲了Flutter的装饰器Decoration Flutter基础入门&#xff1a;装饰器Decoration 装饰器就可以帮我们实现各种Shape效果 但上篇文章并没有讲如何实现具体的Shape效果 那么具体要怎么做呢&#xff1f;这篇文章就主要讲这块 在Fluter中实现Shape效果时&#xff0c;…

Servlet(一)

目录 1.什么是Servlet 2.servlet程序 2.1 创建项目 2.2 引入依赖 2.3 创建目录 2.4 编写代码 2.5 打包程序 2.6 部署程序 2.7 验证程序 3.更简单的部署方法 3.1 安装 3.2配置 4.访问出错怎么办 4.1 404 4.2 405 4.3 500 4.4 空白页面 4.5 无法访问此页面 5.se…

Gin web框架初步认识

Goland使用及gin框架下载引入 第一次使用Goland时需要配置GOROOT、GOPATH、Go Modules 配置完成后进入面板&#xff0c;右键选择Go Modules文件&#xff0c;或者在go工作区通过命令go mod init [name]创建go mod项目。 创建完的项目一般都有go.mod文件和go.sum&#xff0c;前者…

Mysql【安装教程】

Mysql安装教程 1.安装教程 可以去官网下载这个版本的&#xff1a;mysql-installer-community-8.0.31.0 双击点开&#xff0c;选择自定义&#xff1a; 选择主键&#xff1a;左边选择之后就点蓝色按钮添加到右边去&#xff0c;next&#xff1a; 如果出现这个页面&#xff0c…

机器视觉检测系统的基本流程你知道吗

工业制造业种&#xff0c;首先我们便需要了解其基本流程&#xff0c;作为工厂信息科人员&#xff0c;我们不能只依靠视觉服务商的巡检驻检来解决问题&#xff0c;为了产线的效率提升&#xff0c;我们更多的应该培养产线技术人员&#xff0c;出现问题便可以最快速度解决问题&…

领跑新能源车市“下半场”,这家企业凭什么?

中国新能源汽车市场行至下半场&#xff0c;将围绕技术升级、产品竞争力比拼、整合淘汰等趋势快速发展。 4月7日&#xff0c;在北京水立方发布的奇瑞新能源之夜上&#xff0c;奇瑞汽车全面展示新战略、新技术、新品牌和新产品&#xff0c;宣布将以全新的技术生态加速向全球科技…

光伏电池片技术N型迭代,机器视觉检测赋能完成产量“弯道超车”

电池片是光伏发电的核心部件&#xff0c;其技术路线和工艺水平直接影响光伏组件的发电效率和使用寿命。随着硅料、硅片技术逐渐接近其升级迭代空间的瓶颈&#xff0c;电池片环节正处于技术变革期&#xff0c;是光伏产业链中迭代最快的部分。P型中PERC电池片是现阶段市场的主流产…