动态sql

2023-05-16

1.什么是动态sql

sql的内容是变化的, 可以根据条件获取到不同的sql语句.
主要是where部分发生变化。
动态sql的实现, 使用的是mybatis提供的标签

2.为什么使用动态sql

使用动态sql可以解决某些功能的使用 例如使用条件查询某个商品 你输入价格,地区等等进行筛选,如果使用静态sql可能会查询出来的是一个空内容 但使用动态sql可以很好的解决这种问题 例如
在这里插入图片描述

3.动态sql的标签

在这里插入图片描述

3.1 if标签-单条件判断

作用:筛选条件语句
dao层方法为:

public User findConditon(@Param("name")String name, @Param("email")String email);

mapper层

 <!--如果姓名不为空则安姓名查找 如果姓名为空则按邮箱查找 否则查询全部-->
    <select id="findConditon" resultType="com.wx.entity.User">
        select * from tbl_user02
        <where>
            <if test="name!=null and name!=''">
                and name = #{name}
            </if>
            <if test="email!=null and email!=''">
                and email = #{email}
            </if>
        </where>
    </select>

3.2 choose标签 多条件分支判断

//当三者不为空的时候 按姓名 密码 邮件查询 三个条件都会执行一遍
public User findByCondition(@Param("name")String name, @Param("email")String email,
                                @Param("pwd")String pwd);
                                
<select id="findByCondition" resultType="com.wx.entity.User">
        select * from tbl_user02
        <where>
            <choose>
                <when test="name!=null and name!=''">
                    and name = #{name}
                </when>
                <when test="email!=null and email!=''">
                    and email = #{email}
                </when>
                <otherwise>
                    and pwd = #{pwd}
                </otherwise>
            </choose>
        </where>
    </select>

3.3 where语句

如果不使用where语句 就要在where其他判断语句前加入1=1 如 select * from tbl_user02 where 1=1加其他的if判断语句 如果我们不加入这个1=1就可以直接使用where语句 上面的choose和if都搭配使用 使用where 语句 可以自动消除第一个条件中的and 且加上where 例子如上面两个标签中即可

3.4set标签

这个标签配合if标签一起用 一般用于修改语句 如果传递的参数为null 那么就不会修改该列的值

 public int updateUser(User user);

//这里注意 test="参数" 这里的参数 是前端传过来的值就是你前端页面上是什么 这里就要写什么 
//而下面的name=#{name} 第一个name是你数据库中的字段 #{name}中是你的前端传过来的值
<update id="updateUser" parameterType="User">
        update tbl_user02
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="pwd!=null">
                pwd=#{pwd},
            </if>
            <if test="email!=null">
                email=#{email},
            </if>
        </set>
        where id = #{id}
    </update>

3.4foreach标签

循环标签 适用于批量添加、删除 和查询记录

3.4.1用于批量查询

查询id为1 3 5 的用户信息
正常sql语句为 select * from tbl_user02 where id in(1,3,5);
下面的为使用foreach遍历 循环查询
    解释:
    <foreach collection="集合类型" open="开始的字符" close="结束的字符"
	    item="集合中的成员" separator="集合成员之间的分割符">
        #{item的值}
    </foreach>
   标签属性:
   collection:表示循环的对象是数组还是list集合。如果dao方法的形参是数组,collection="array";
		如果dao方法形参是list,collection="list";
   open:循环开始的字符。sql.append("(");
   close:循环结束的字符。sql.append(")");
   item:集合成员,自定义的变量。Integer item = idList.get(i);
   separator:集合成员之间的分隔符。sql.append(",");
   #{item的值}:获取集合成员的值;

具体代码实现
dao层

//传递的参数为id数组所以mapper层的collection="list"
public List<User> findByIds(Integer[] ids);

mapper层为

    <select id="findByIds" resultType="com.wx.entity.User">
        select * from tbl_user02 where id in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </select>

测试类为:

@Test
    public void testFindByIds() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        Integer[] ids = {1,3,5};
        List<User> user = userDao.findByIds(ids);
        System.out.println(user);
        session.close();
    }

查询出三条记录
在这里插入图片描述

3.4.2用于批量删除

dao层

public int BatchDelete(Integer[] ids);

mapper层

  <delete id="BatchDelete">
        delete from tbl_user02 where id in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

测试类:

@Test
    public void testBatchDelete() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        Integer[] ids = {1,3,5};
        int row = userDao.BatchDelete(ids);
        System.out.println(row);
        session.commit();
        session.close();
    }

在这里插入图片描述

3.4.3用于批量添加

dao层

public int batchAdd(List<User> users);

mapper层

   <!--注意 因为循环添加的为一个对象 所以下面添加的值就必须是users.name ...-->
    <insert id="batchAdd">
        insert into tbl_user02(name,pwd,email) values
        <foreach collection="list" item="users" separator=",">
            (#{users.name},#{users.pwd},#{users.email})
        </foreach>

    </insert>

测试类:

@Test
    public void testBatchAdd() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        List<User> list = new ArrayList<User>();
        list.add(new User("张三","123","zs@qq.com"));
        list.add(new User("李四","123","ls@qq.com"));
        list.add(new User("王五","123","ww@qq.com"));
        int row = userDao.batchAdd(list);
        System.out.println(row);
        session.commit();
        session.close();
    }

在这里插入图片描述

3.4.4sql片段

一般用于查询语句的时候 select * … 这种不推荐 所以用sql片段可以很好的解决这个问题
在这里插入图片描述

4.mybatis映射文件处理特殊字符.

当我们使用条件语句查询的时候 就比如在某个范围中使用条件如 money>100 and money<200
这个条件在mapper中无法直接写所以需要特殊处理,有两种解决办法:

   第一种:转义标签 &nbsp; &lt;  
   第二种: <![CDATA[sql]]>

<select id="findByMaxAndMin" resultType="com.ykq.entity.Account">
       <![CDATA[select * from account where id >#{min} and id <#{max}]]>
</select>

第一种:转义字符处理
dao层

 public User findByMaxAndMin(@Param("min") int min,@Param("max") int max);

mapper层

 <select id="findByMaxAndMin" resultType="com.wx.entity.User">
        select * from tbl_user02 where id &gt;#{min} and id &lt; #{max}
    </select>

测试类

    @Test
    public void testFindByMaxMin() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        User user = userDao.findByMaxAndMin(1, 3);
        System.out.println(user);
        session.commit();
        session.close();
    }

在这里插入图片描述
第二种: <![CDATA[sql]]>

dao层

public User findByMaxAndMin01(@Param("min") int min,@Param("max") int max);

实体层

<select id="findByMaxAndMin01" resultType="com.wx.entity.User">
         <![CDATA[select * from tbl_user02 where id>#{min} and id<#{max}]]>
    </select>

测试类

 @Test
    public void testFindByMaxMin01() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        User user = userDao.findByMaxAndMin01(1, 3);
        System.out.println(user);
        session.commit();
        session.close();
    }

在这里插入图片描述

5.mybatis完成模糊查询

语法:select * from 表名 where 列名 like ‘%a%’ 但是% a %这样在mapper层无法使用 解决办法有两种
第一种:使用字符串函数(concat)完成拼接
dao层

    /*模糊查询*/
    public User findByName(@Param("name")String name);

mapper层

<select id="findByName" resultType="com.wx.entity.User">
        select * from tbl_user02 where name like concat('%',#{name},'%');
    </select>

测试类

    @Test
    public void testFindByName() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        User user = userDao.findByName("李");
        System.out.println(user);
        session.close();
    }

在这里插入图片描述
第二种:使用${}

 <select id="findByName" resultType="com.wx.entity.User">
        select * from tbl_user02 where name like '%${name}%';
    </select>

两者区别:concat不能解决sql注入的问题 第二种是预编译 可以解决sql注入问题

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态sql 的相关文章

  • 在 Django shell 会话期间获取 SQL 查询计数

    有没有办法打印 Django ORM 在 Django shell 会话期间执行的原始 SQL 查询的数量 Django 调试工具栏已经提供了此类信息 例如 5 QUERIES in 5 83MS但如何从 shell 中获取它并不明显 您可
  • 结果集未打开。验证自动提交已关闭。阿帕奇·德布里

    我的数据库使用 apache derby 我能够对数据库执行插入操作 以下是尝试显示我唯一的表 MAINTAB 的内容的代码摘录 java sql Connection 的实例是 dbconn ResultSet word Statemen
  • 从两个表中搜索然后删除

    我有两个包含成员数据的表 与 member id 列链接 我需要搜索所有记录email列以 pl 结尾 然后 我需要为此删除两个表中的所有记录 基于 member id 是否可以通过一条 SQL 语句完成此操作 SELECT member
  • SQL Server 2012(代号:Denali)CTP 3的FIRST_VALUE和LAST_VALUE的实际用途是什么

    随着 Denali 的 CTP 3 版本的发布 我们有了更多的分析功能 其中我对其中两个感兴趣 a 第一个值 http msdn microsoft com en us library hh213018 28v SQL 110 29 asp
  • SQL使用多个/相关列计算项目频率?

    我对 SQL 完全陌生 并且阅读了有关 SQL 的 StackOverflow 帖子来尝试弄清楚这一点 以及其他来源 但无法在 SQL 中执行此操作 开始 我有一个 3 列和数千行的表 其中包含前 2 列的数据 第三列当前为空 我需要根据第
  • 混合语言源目录布局

    我们正在运行一个使用多种不同语言的大型项目 Java Python PHP SQL 和 Perl 到目前为止 人们一直在自己的私有存储库中工作 但现在我们希望将整个项目合并到一个存储库中 现在的问题是 目录结构应该是什么样的 我们应该为每种
  • MySQL:你能指定一个随机限制吗?

    有没有办法在 SQL MySQL 中随机化限制数字 我希望能够做的是在查询中获取随机数量的结果以在插入子查询中使用 而无需任何服务器端脚本 我希望能够作为假设说明运行的查询是 SELECT id FROM users ORDER BY RA
  • 返回行位置 - Postgres

    我返回一个带有位置的表 select from select row number over as position from organization result where data1 Hello 返回这个 这是正确的 data1 H
  • Postgresql 中的 id 列位置重要吗?

    我正在测试删除主键列 id 的迁移 我想使用外键作为主键 当我运行并恢复迁移时 我看到表的状态是相同的 只是 id 列现在是最后一个 它会以任何方式改变我的数据库的行为吗 我是否应该费心去恢复迁移恢复代码中的列顺序 理论上一切都应该没问题
  • (SQL) 识别字段中字符串格式多次出现的位置

    我需要将叙述字段 自由文本 拆分为多行 目前的格式如下 Case Reference Narrative XXXX XX 123456 Endless Text up to 50k characters 在作为文本的叙述字段中 各个条目 当
  • 如何打印Oracle中过程的定义?

    oracle中有没有办法查看过程的结构是什么 我正在尝试记录并运行程序 并希望将实际的程序结构存储在我的日志中 您可以查询ALL SOURCE table SELECT text FROM all source WHERE owner lt
  • SQL Server 查询结果集的大小

    SQL Server 中是否有确定结果集中 Mgmt Studio 查询中返回的数据大小 以 MEGS 为单位 您可以打开客户端统计信息 查询菜单 包括客户端统计信息 它给出执行查询时从服务器返回的字节数
  • 使用MySQL计算单个表中借方和贷方的余额

    下面的 MySQL 表包含带有关联金额的借方或贷方 操作 如何选择具有非零 余额 的所有 CLIENT ID 我尝试将表连接到自身以计算所有借方和贷方总额 但有些东西无法正常工作 CLIENT ID ACTION TYPE ACTION A
  • SQL - 为每条记录调用存储过程

    我正在寻找一种方法来为 select 语句的每条记录调用存储过程 SELECT SomeIds SELECT spro Id FROM SomeTable as spro INNER JOIN Address addr ON addr Id
  • Quartz.NET 设置 MisfireInstruction

    我正在使用 Quartz NET 在 C 中工作 并且在 CronTrigger 上设置失火指令时遇到问题 我正在运行安装了 Quartz DB 的 SQL 后端 我有以下代码 可以很好地创建作业和运行调度程序 IScheduler sch
  • 如果执行没有事务的删除语句,是否会删除部分内容?

    如果表myTable包含100000000条记录 我执行DELETE FROM myTable 没有开始交易并且出现问题 例如服务器电源故障 会删除一些记录吗 否 如果数据库引擎符合ACID http en wikipedia org wi
  • 消息 102,级别 15,状态 1,第 1 行“ ”附近的语法不正确

    我试图从临时表中查询 但不断收到此消息 Msg 102 Level 15 State 1 Line 1 Incorrect syntax near 有人能告诉我问题是什么吗 是因为要转换吗 查询是 select compid 2 conve
  • 更新plpgsql中触发器函数中的多列

    给出以下架构 create table account type a id SERIAL UNIQUE PRIMARY KEY some column VARCHAR create table account type b id SERIA
  • 将多行合并为一行并根据行数附加列

    我正在尝试将同一个表的多行合并为一个 我有一个像这样的示例表 Col1 Col2 Col3 Col4 Col5 Col6 1 BH1 CB 12 CC CC Conveyor Mal 1 BH1 CB 104 ZC ZC Full Emp
  • Oracle:如果表存在

    我正在为 Oracle 数据库编写一些迁移脚本 并希望 Oracle 有类似于 MySQL 的东西IF EXISTS构造 具体来说 每当我想删除 MySQL 中的表时 我都会执行类似的操作 DROP TABLE IF EXISTS tabl

随机推荐

  • HDFS API操作

    HDFS API操作 实验环境 Linux Ubuntu 16 04 前提条件 xff1a 1 xff09 Java 运行环境部署完成 2 xff09 Hadoop 的单点部署完成 上述前提条件 xff0c 我们已经为你准备就绪了 实验内容
  • HBase的安装部署和使用

    HBase的安装部署和使用 文章目录 HBase的安装部署和使用实验环境实验内容实验步骤1 点击 34 命令行终端 34 xff0c 打开新的命令行窗口2 解压安装包3 更改文件夹名和所属用户4 设置HBASE HOME环境变量5 修改hb
  • 熟悉常用的HBase操作

    熟悉常用的HBase操作 文章目录 实验环境实验内容1 编程实现以下指定功能 xff0c 并用Hadoop提供的HBase Shell命令完成相同的任务 xff08 1 xff09 列出HBase所有的表的相关信息 xff0c 如表名 创建
  • Hive的安装部署和管理

    Hive的安装部署和管理 文章目录 实验环境实验内容实验步骤1 点击 34 命令行终端 34 xff0c 打开新窗口2 解压安装包3 更改文件夹名和所属用户4 设置HIVE HOME环境变量5 导入MySql jdbc jar包到hive
  • Hive数仓:使用桶表

    Hive数仓 xff1a 使用桶表 文章目录 Hive数仓 xff1a 使用桶表实验环境实验步骤1 点击 34 命令行终端 34 xff0c 打开新窗口2 启动MySQL3 指定元数据数据库类型并初始化Schema4 启动Hadoop5 启
  • python 获取当前文件路径

    一 Python 获取当前文件路径方法 sys path 0 获取文件当前工作目录路径 绝对路径 sys argv 0 获得模块所在的路径 由系统决定是否是全名 若显示调用python指令 xff0c 如python demo py xff
  • PySpark中的RDD基本操作

    PySpark中的RDD基本操作 课程性质 xff1a PySpark数据处理 文章目录 1 实验目标2 本次实验主要使用的 P y t h
  • PySpark中的RDD创建

    PySpark中的RDD创建 课程性质 xff1a PySpark数据处理 文章目录 1 实验目标2 本次实验主要使用的 P y t h
  • el-table-column的formatter的使用

    当后端返回来的数据格式需要再去处理 xff1b 可以使用formatter属性 lt el table column label 61 34 性别 34 align 61 34 center 34 formatter 61 34 genda
  • 提示“无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系“的解决方案

    使用sudo apt get install lt packgename gt 时出现提示无法修正错误 xff0c 因为您要求某些软件包保持现状 xff0c 就是它们破坏了软件包间的依赖关系 可以换个命令 sudo aptitude ins
  • aosp下载、编译、刷机和单编framework(android 12)

    我的设备 xff1a 咸鱼上买的pixel 3a 一 aosp下载 1 安装repo mkdir bin PATH 61 bin PATH curl sSL 39 https gerrit googlesource proxy ustclu
  • LAMP架构之mysql的安装部署

    mysql的安装部署 一 mysql编译安装1 编译过程 二 LAMP架构的部署 一 mysql编译安装 官网地址如下 xff0c 进入选择版本 xff1a https downloads mysql com archives commun
  • hexo博客绑定自己的域名

    hexo博客绑定自己的域名 学习网址1 学习网址2 学习网址3 一 购买域名 登录阿里云账号 控制台 搜索框输入域名 域名注册 输入需要注册的域名 xff08 查看是否被占用 xff09 加入购物车 xff08 显示不能备案的不可买 xff
  • SimpleDateFormat类 格式化日期

    功能 xff1a 格式化和解析日期 将Date类型的日期格式化成我们需要的日期类型一般是 字符串类型将字符串类的日期再转回来 用到两个方法 format Date date xff1a 将date型转换成特定格式的字符串 parse Str
  • 队列(Java实现)

    1 1应用场景 银行排队 xff1a 1 2基本介绍 特点 队列是一个有序列表 xff0c 可以用数组或是链表来实现 遵循先入先出的原则 即 xff1a 先存入队列的数据 xff0c 要先取出 后存入的要后取出 示意图 解释 MaxSize
  • IO字节流读取文本中文乱码

    1 1问题说明 我们都知道字符流适用于读取文本 xff0c 而字节流能读取文本 照片 视频等 xff0c 但是用字节流读取文本到我们程序的控制台中会出现中文乱码的情况 xff0c 如下图 我的文本中的数据是 生活很简单 xff0c 过了今天
  • glibc所安装的工具程序

    catchsegv 当程序发生segmentation fault的时候 用来建立一个 堆栈跟踪 gencat 建立消息列表 getconf 针对文件系统的指定变量显示其系统设置值 getent 从 系统管理数据库获取一个条目 glibcb
  • 单链表(java实现)

    1 1 链表 Linked List 介绍 链表是有序的列表 xff0c 但是它在内存中是存储如下 链表是以节点的方式来存储 是链式存储每个节点包含 data 域 xff0c next 域 xff1a 指向下一个节点 如图 xff1a 发现
  • prepareStatement的使用

    1 1prepareStatement解决sql注入的问题 span class token comment 演示sql注入的安全问题 span span class token keyword public span static voi
  • 动态sql

    1 什么是动态sql sql的内容是变化的 可以根据条件获取到不同的sql语句 主要是where部分发生变化 动态sql的实现 使用的是mybatis提供的标签 2 为什么使用动态sql 使用动态sql可以解决某些功能的使用 例如使用条件查