你不能不知道的Mydatis扩展:动态sql以及模糊查询,结果映射!

news2024/12/23 5:00:38

一.Mydatis中的动态sql

1.Mydatis中的动态sql出现背景?

任何技术的出现都不是空穴来风,一切都是有迹可循的!而动态sql同样如此!

1.1传统sql语句

MyBatis 中出现动态 SQL 的背景是:为了解决传统 SQL 查询的静态性和硬编码的问题。传统的 SQL 查询语句是静态的,即在编写查询语句时需要明确指定所有的条件和参数,无法根据不同的情况生成不同的 SQL 语句。这样会导致以下一些问题:

  1. 条件判断的处理:在实际的查询中,往往需要根据不同的条件组合生成不同的查询语句,传统的静态 SQL 很难应对这种情况。

  2. 可读性和可维护性:当 SQL 查询语句过于复杂或包含大量的条件判断时,代码可读性和可维护性变得困难,容易出现错误。

  3. 重复代码:如果多个查询语句之间只有部分条件不同,使用传统的静态 SQL 会导致大量的重复代码,增加了开发和维护的工作量。

1.2改良的mydatissql优势

为了解决这些问题,MyBatis 引入了动态 SQL 功能,允许开发者在运行时根据不同的条件生成不同的 SQL 语句,从而提供灵活的查询能力。动态 SQL 具有以下优点:

  1. 灵活性:动态 SQL 允许根据不同的条件生成不同的 SQL 语句,满足各种查询需求。开发者可以根据实际情况动态组装 SQL 语句,而不需要硬编码所有可能的情况。

  2. 可读性和可维护性:通过使用动态 SQL 标签,可以更清晰地表达查询的逻辑,并减少重复代码。这提高了代码的可读性和可维护性,降低了出错的概率。

  3. 参数处理:动态 SQL 允许方便地处理参数,可以根据参数的值决定是否包含相关的查询条件或语句片段。

总之,动态 SQL 是 MyBatis 中的一个重要特性,它解决了传统 SQL 查询的静态性和硬编码的问题,使得查询语句更加灵活、可读性更高,并且减少了重复代码的编写。这为开发者带来了更好的开发体验和效率。

2.mydatis中的一些常用动态sql标签

2.1 if标签:它用于根据条件判断是否包含某一部分 SQL 语句

<select id="getUserList" parameterType="User" resultType="User">
  SELECT * FROM user
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

2.2  <choose><when><otherwise> 标签  实现类似于 switch-case 的逻辑判断

<select id="getUserList" parameterType="User" resultType="User">
  SELECT * FROM user
  <where>
    <choose>
      <when test="name != null">
        AND name = #{name}
      </when>
      <when test="age != null">
        AND age = #{age}
      </when>
      <otherwise>
        AND status = 'ACTIVE'
      </otherwise>
    </choose>
  </where>
</select>

2.3trim> 标签:它可以根据条件去除或添加 SQL 语句的一部分,例如去除开头或结尾的逗号

<select id="getUserList" parameterType="User" resultType="User">
  SELECT *
  FROM user
  <trim prefix="WHERE" prefixOverrides="AND | OR">
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </trim>
</select>

2.4<foreach> 标签,用于循环遍历集合或数组,并将集合中的元素应用到 SQL 语句中的特定部分

2.4.1<foreach> 标签包含的属性名

  • collection:指定要遍历的集合或数组的名称。
  • item:指定每次遍历时的当前元素的别名。
  • index:指定每次遍历时的索引的别名。
  • open:指定循环开始时要添加的字符串。
  • close:指定循环结束时要添加的字符串。
  • separator:指定每次循环之间要添加的字符串。

2.4.2实例

<select id="getUserList" parameterType="java.util.List" resultType="User">
  SELECT * FROM user
  WHERE id IN
  <foreach collection="list" item="id" open="(" close=")" separator=",">
    #{id}
  </foreach>
</select>
在上述示例中,我们

在上述示例中,我们使用 <foreach> 标签循环遍历名为 list 的集合,将集合中的元素应用到 SQL 语句的 IN 子句中,生成类似于 WHERE id IN (1, 2, 3) 的查询语句。

通过使用 <foreach> 标签,我们可以方便地处理集合或数组中的元素,动态生成适应不同数据集合的 SQL 语句

二.mybatis中的模糊查询

1.三种模糊查询

实现接口方法,和测试类

List<Book> like1(@Param("bname") String bname);

    List<Book> like2(@Param("bname") String bname);

    List<Book> like3(@Param("bname") String bname);

 

 @Test
    public void testlike1() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }
    @Test
    public void testlike2() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }
    @Test
    public void testlike3() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }

1.1普通模糊查询版本

<select id="like1"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like
  </select>

通过此版本进行sql的调用以及功能的实现,在控制台将会打印出所需要查询的数据。而sql语句不会被打印出来,响应结果也没有!所以有缺陷,慢慢的被淘汰了

测试打印结果

 

1.2$版本的的模糊查询

<select id="like2"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like  '${bname}'
  </select>

只是传参数时占位符的形式  有sql'语句的打印,标签没有响应结果,而且需要查询的参数要 ' ' 包裹!

测试打印结果

 1.3 #版本的模糊查询

<select id="like3"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like concat ('%', #{bname},'%')
  </select>

预处理sql,有sql语句的打印并且也有参数的回显,在目前的主流企业开发中经常用到

打印测试结果

 2. $和#的区别

2.1# 参数替换方式(预编译方式)

# 是用于预编译阶段的占位符,会将传入的参数值以安全的方式替换到 SQL 语句中。

# 的使用方式是将参数直接嵌入 SQL 语句中,通常在字符串常量、数字等类型的参数值前后都会自动添加单引号或其他必要的转义符号,以确保参数被正确处理。

# 在模糊查询中使用时,可以直接拼接 % 通配符,例如:SELECT * FROM table_name WHERE column_name LIKE CONCAT('%', #{keyword}, '%')

使用 # 可以有效防止 SQL 注入攻击,因为传入的参数值会经过预编译处理,不会被当作 SQL 的一部分进行解析。

2.2 $ 参数替换方式(文本替换方式):

$ 是直接将参数值拼接到 SQL 语句中,没有任何预编译的过程。

$ 的使用方式是直接将参数值嵌入到 SQL 语句中,不会进行任何转义或处理

$ 在模糊查询中使用时,需要手动拼接 % 通配符,例如:SELECT * FROM table_name WHERE column_name LIKE '%' || ${keyword} || '%'

使用 $ 时需要特别注意防止 SQL 注入攻击,因为参数值会直接替换到 SQL 语句中,可能会导致安全问题。l

综上所述,# 是推荐使用的参数替换方式,特别是在用户输入参与的查询中,能够提供更好的安全性。而 $ 则需要谨慎使用,确保参数的安全性和正确性。无论选择哪种方式,都应根据具体需求和安全要求来决定。

3.总结

1$占位符传参数,#预处理sql
2外在形式:$不带引号 ,#自带引号
3.$存在sql注入 ,#不存在
sql注入:
4.¥可以做动态列,完成动态sql开发

 

三. mybatis中的结果映射

3.1实例

1.返回单表的所对应的实体类,仅有一个查询结果  可用 resulttype :resultmap

2.返回单表的所对应的实体类,有多一个查询结果  可用 resulttype :resultmap
3.返回多表的所对应的实体类,仅有一个查询结果   通常用resulttype  可以用resultmap
4.返回多表的所对应的实体类,有多一个查询结果  通常用resulttype  可以用resultmap
5.返回单个字段,,仅有一个查询结果  只有resulttype
6.返回单个字段,,有多一个查询结果  只有resultty方法实现

3.2代码展示 

<select id="list1" resultMap="BaseResultMap">
  select * from t_mvc_book
</select>
<select id="list2" resultType="com.javaxl.model.Book">
  select * from t_mvc_book
</select>
<select id="list3" resultType="com.javaxl.model.Book" parameterType="com.javaxl.model.BookVo">
  select * from t_mvc_book where bid in
  <foreach collection="bookIds" open="(" close=")" separator="," item="bid">
    #{bid}
  </foreach>
</select>
<select id="list4" resultType="java.util.Map">
  select * from t_mvc_book
</select>
<select id="list5" resultType="java.util.Map" parameterType="java.util.Map">
  select * from t_mvc_book where bid = #{bid}
</select>

/**
 * 使用resultMap返回自定义类型集合
 * @return
 */
List<Book> list1();

/**
 * 使用resultType返回List<T>
 * @return
 */
List<Book> list2();

/**
 * 使用resultType返回单个对象
 * @return
 */
Book list3(BookVo bookVo);

/**
 * 使用resultType返回List<Map>,适用于多表查询返回结果集
 * @return
 */
List<Map> list4();

/**
 * 使用resultType返回Map<String,Object>,适用于多表查询返回单个结果集
 * @return
 */
Map list5(Map book);





测试代码
 @Test
    public void testListReturn() {
        List list = new ArrayList();
        list.add("19");
//        list.add("20");
        BookVo bookVo = new BookVo();
        bookVo.setBookIds(list);
//        使用resultMap返回自定义类型集合
//        List<Book> books = bookService.list1();

//        使用resultType返回List<T>
//        List<Book> books = bookService.list2();

//        使用resultType返回单个对象
//        Book books = bookService.list3(bookVo);
//        System.out.println(books);

//        for (Book b : books) {
//            System.out.println(b);
//        }

        //        使用resultType返回List<Map>,适用于多表查询返回结果集
//        List<Map> books = bookService.list4();
//        for (Map book : books) {
//            System.out.println(book);
//        }

        Map map = new HashMap();
        map.put("bid",20);
        Map book = bookService.list5(map);
        System.out.println(book);
    }

3.3总结

  1. resultType

    • resultType 是一种简单的结果映射方式,用于指定查询返回结果的类型。
    • 通过 resultType,可以直接指定一个 Java 类型作为查询结果的映射对象,MyBatis 会根据查询结果自动进行映射。
    • 例如:<resultType type="com.example.User"/>
    • resultType 适用于简单的查询,返回的结果集字段名需要与 Java 类型的属性名一一对应,且类型匹配。
    • 缺点是当查询结果较复杂或者查询语句中有联表查询时,无法满足灵活的映射需求。
  2. resultMap

    • resultMap 是一种更为灵活和复杂的结果映射方式,用于自定义查询结果的映射规则。
    • 通过 resultMap,可以自定义每个结果字段与 Java 对象属性之间的映射关系,支持复杂的嵌套和联表查询映射。
    • 使用 resultMap 需要在映射文件中定义具体的 resultMap 配置,指定字段和属性的对应关系。
    • 例如:
       

      复制代码

      <resultMap id="userResultMap" type="com.example.User"> <id property="id" column="user_id"/> <result property="username" column="user_name"/> <result property="email" column="user_email"/> </resultMap>
    • 在查询语句中可以使用 <resultMap> 元素的 id 属性引用该 resultMap,例如:
       

      复制代码

      <select id="getUser" resultMap="userResultMap"> SELECT user_id, user_name, user_email FROM user WHERE user_id = #{userId} </select>
    • resultMap 提供了更大的灵活性,可以处理各种复杂的映射需求,但相对于 resultType 需要更多的配置和定义。

综上所述,resultType 适用于简单的查询,并且查询结果与 Java 对象属性一一对应的情况。而 resultMap 则更适用于复杂的查询,需要自定义字段和属性的映射关系,包括嵌套对象和联表查询等情况。根据具体的业务需求和查询复杂度,选择合适的方式来进行结果映射。

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

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

相关文章

vim 常见操作

Vim 工作模式 1、vim 三种基本的工作模式 vim有三种基本的工作模式&#xff0c;分别为&#xff1a;命令模式、末行模式、编辑模式。关于这三种工作模式的介绍&#xff0c;请见下文。 1.1、命令模式 使用vim打开文件之后&#xff0c;首先进入命令模式&#xff0c;它是vim编辑…

面试之快速学习STL-常用算法

1. 排序算法 sort() 函数是基于快速排序实现的&#xff0c;故不保证相对位置&#xff0c;但是stable_sort (first, last)保证&#xff0c;它基于归并排序。sort()只适用于支持随机迭代器的容器&#xff08;array, vector, deque&#xff09;&#xff0c;好理解&#xff0c;毕竟…

Mysql 开窗函数(窗口函数)

文章目录 全部数据示例1&#xff08;说明&#xff09;开窗函数可以比groupby多查出条件列外的字段&#xff0c;开窗函数主要是为了跟聚合函数一起使用&#xff0c;达到分组统计效果&#xff0c;并且开窗函数的结果集基本都是跟总行数一样示例2示例3示例4错误示例1错误示例2错误…

基于vue的小说阅读网/基于springboot的小说网站/阅读网站的设计与实现

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

学习设计模式之享元模式,但是宝可梦

前言 作者在准备秋招中&#xff0c;学习设计模式&#xff0c;做点小笔记&#xff0c;用宝可梦为场景举例&#xff0c;有错误欢迎指出。 享元模式 1 介绍 享元模式很好理解&#xff0c;它主要是为了减少创建对象的数量&#xff0c;属于结构型设计模式 目的&#xff1a;减少…

【第三阶段】kotlin语言的内置函数run

1.run函数返回类型是根据匿名函数最后一行的类型变化而变化 run 函数里面持有的是this fun main() {val info"kotlin is ok"var r info.run {true}println(r) }执行结果 2.run搭配具名函数 package Stage3fun main() {val info"kotlin is ok"var r info…

IAR编译报错 ErrorLi005]: no definition for

IAR编译报错 ErrorLi005]: no definition for… 具体报错如下图所示&#xff1a; 错误原因&#xff1a;出现此问题是由于没有写 VehicleDriveStatusCheck 此功能函数&#xff0c;而程序中其他地方调用此函数而导致的错误 解决措施&#xff1a;编写 VehicleDriveStatusCheck …

docker的安装以及基本操作

一.认识docker Docker是一种用于构建、打包和运行应用程序的开源平台。它基于操作系统级虚拟化技术&#xff0c;可以将应用程序和其依赖的库、环境等资源打包到一个可移植的容器中&#xff0c;形成一个轻量级、独立的可执行单元。 开发者在本地编译测试通过的容器可以批量地在…

Win 7 修改开机密码,使用F8修复提前终止导致蓝屏

前言 一台win7一体机密码突然不对&#xff0c;也不知道怎么回事就登录不了 使用PE中的NTPWEdit查看修改密码&#xff0c;没有用户列表 步骤 正常启动或者按F8&#xff0c;选择修复 正常电脑如下显示 这种可以直接使用PE改密码&#xff0c;就不放图了 问题电脑如下显示…

kafka--技术文档--基本docker中安装<单机>-linux

安装zookeeper 阿丹小科普&#xff1a; Kafka在0.11.0.0版本之后不再依赖Zookeeper&#xff0c;而是使用基于Raft协议的Kafka自身的仲裁机制来替代Zookeeper。具体来说&#xff0c;Kafka 2.8.0版本是第一个不需要Zookeeper就可以运行Kafka的版本&#xff0c;这被称为Kafka Raf…

C#详解-Contains、StartsWith、EndsWith、Indexof、lastdexof

目录 简介: 过程: 举例1.1 举例1.2 ​ 总结: 简介: 在C#中Contains、StarsWith和EndWith、IndexOf都是字符串函数。 1.Contains函数用于判断一个字符串是否包含指定的子字符串&#xff0c;返回一个布尔值&#xff08;True或False&#xff09;。 2.StartsWith函数用于判断一…

Vue Element upload组件和Iview upload 组件上传文件

今天要分享的是使用这俩个UI组件库的upload组件分别实现调用组件本身的上传方法实现和后台交互。接下来就是开车的时间&#xff0c;请坐稳扶好~ 一、element upload组件传送门 1、html文件 <el-upload ref"uploadRef" :action"uploadUrl" :data"…

第五讲:常见的BeanPostProcessor

常见的BeanPostProcessor 一、入门Demo二、添加BeanPostProcessor1. AutowiredAnnotationBeanPostProcessor2. CommonAnnotationBeanPostProcessor3. ConfigurationPropertiesBindingPostProcessor 前文我们简单讲了Bean的生命周期&#xff0c;以及生命周期的前后&#xff0c;本…

科大讯飞AI大模型,太猛了!

最近几个月&#xff0c;以ChatGPT为代表的AIGC迅速崛起&#xff0c;国内头部科技企业之间也掀起了百模大战&#xff0c;在众多的大模型当中我比较看好的一家就是&#xff1a;科大讯飞。 我很早就通过科大讯飞老朋友&#xff0c;拿到了体验账号&#xff0c;简单体验了一下&…

C++新经典06-- 语言特性

1.继承性、多态性、封装性。 2.C本身是属于编译型语言。 什么叫编译型语言呢&#xff1f;程序在执行之前需要一个专门的编译过程&#xff0c;把程序编译成二进制文件&#xff08;可执行文件&#xff09;&#xff0c;执行的时候&#xff0c;不需要重新翻译&#xff0c;直接使用…

shell脚本中linux命令的特殊用法记录

shell脚本中linux命令的特殊用法记录 1、linux命令特殊参数选项1.1、sed -e1.2、echo -e 2、 shell 扩展2.1、[[ ]]支持用~进行正则匹配 3、特殊命令用法3.1、{} 变量替换 1、linux命令特殊参数选项 1.1、sed -e sed -e以严格模式执行脚本&#xff0c;在sed -e 后面的所有命令…

反转链表II

江湖一笑浪滔滔&#xff0c;红尘尽忘了 题目 示例 思路 链表这部分的题&#xff0c;不少都离不开单链表的反转&#xff0c;参考&#xff1a;反转一个单链表 这道题加上哨兵位的话会简单很多&#xff0c;如果不加的话&#xff0c;还需要分情况一下&#xff0c;像是从头节点开始…

【Apollo学习笔记】——规划模块TASK之PATH_BORROW_DECIDER

文章目录 前言PATH_BORROW_DECIDER功能简介PATH_BORROW_DECIDER相关配置PATH_BORROW_DECIDER总体流程PATH_BORROW_DECIDER相关子函数IsNecessaryToBorrowLaneIsBlockingObstacleFarFromIntersectionIsNonmovableObstacleCheckLaneBorrow 参考 前言 在Apollo星火计划学习笔记—…

MySql014——分组的GROUP BY子句和排序ORDER BYSELECT子句顺序

前提&#xff1a;使用《MySql006——检索数据&#xff1a;基础select语句》中创建的products表 一、GROUP BY子句基础用法 SELECT vend_id, COUNT(*) AS num_prods FROMstudy.products GROUP BY vend_id;上面的SELECT语句指定了两个列&#xff0c;vend_id包含产品供应商的ID&…

Protobuf 语法详解

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…