MyBatis查询数据库之三(#{}vs${},like查询,resultMap,as,多表查询)

news2024/9/30 3:28:36

目录

查询操作

1.单表查询

1.1 参数占位符#{}和${}

1.2 ${}的优点

1.3 sql注入问题

​编辑

面试常问:${}与#{}的区别

1.4 like查询

2.多表查询

2.1 返回字典映射:resultMap

2.2 多表查询

(1)建立 Articalinfo 实体类:

(2)在 ArticleMapper 接口中写出通过用户id查询用户的方法

(3)在ArticleMapper.xml中实现接口的方法

(4)生成测试方法


查询操作

1.单表查询

下面我们来实现⼀下根据用户 id 查询用户信息的功能

UserController 实现代码如下:


    @RequestMapping("/getuserbyid")
    public Userinfo geUserById(Integer id){
        if (id==null)
            return null;
        return userService.getUserById(id);
    }

UserMapper 实现代码如下:

/**
     * 根据用户id查询用户信息
     * @param id
     * @return
     */
    Userinfo getUserById(@Param("id") Integer id);

UserMapper.xml 实现代码如下:

<select id="getUserById" resultType="com.example.ssmdemo1.entity.Userinfo">
        select * from userinfo where id=${id}
</select>

1.1 参数占位符#{}和${}

  • #{}:预编译处理
  • ${}:字符直接替换

预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使用 PreparedStatement 的 set 方法来赋值。

直接替换:是MyBatis 在预处理 ${} 时,就会把 ${} 替换成变量的值。

在正常的我们用id来查询用户时:

都是没问题的,但是当我们用username来查询时:

可以看到在我们使用 # 符时是占位符,使用 $ 符则是直接替换了,int类型的自然没有问题,但是字符串类型的就有问题了

对于MySQL是要加单引号的,而$是啥都不加,所以是错误的!!

1.2 ${}的优点

有人会说,#{}这么好使的话为什么还会有${}的存在呢?

在进行排序时(需要传递关键字时)需要使用到${},而 #{sort} 就不能实现排序查询了,因为使用 #{sort} 查询时, 如果传递的值为 String 则会加单引号,就会导致 sql 错误。 

当使用#{}的时候呢? 

使用$是啥都不管,直接使用原样去替换,#会加上'' 

$使用注意事项:一定是可以穷举的值,在使用之前一定要对传递的值进行合法性验证(安全性验证)。

1.3 sql注入问题

先看两则对比:

在这里${}完美体现了它自身的特性,但是当我们改变一下password:

 这里就细思极恐了,当我们使用'${}'替换#{}的时候会这样,那不是只要我们知道别人的账号就可以登录别人的账户了吗!,我们来看看#{}会不会这样:

我们可以看到 $ 符是存在SQL注入的问题,而 # 不存在

我们使用了一个奇怪的字符时为什么会成功呢?

那 # 为什么不会这样呢?

它使用的是JDBC的预处理的方式,它就把password当成字符串即values来处理,只是值的替换,而不是SQl语句,这就是机制的不同的区别 

面试常问:${}与#{}的区别

  1. $ 存在失去了注入问题,而 # 不存在
  2. $ 是直接替换,# 是预处理

1.4 like查询

在使用like查询时,使用#{}会报错,下面我们来看看是怎么回事:

这是因为使用#{}会当作字符串进行替换,就变成下面这样了 

而使用 $ :

这里我们可以看到使用 $ 符是可以的,但是我们说过使用 $ 符一定要能穷举,但是这里的 '李' 是不能够穷举的 ,前面说了使用${}有SQL注入的风险,所有这是不能直接使用 ${},可以考虑使用 mysql 的内置函数 concat() 来处理,实现代码如下: 

<select id="findUserByName3" resultType="com.example.demo.model.User">
     select * from userinfo where username like concat('%',#{username},'%')
</select>

所以在使用like查询时应该搭配concat()函数使用。

2.多表查询

2.1 返回字典映射:resultMap

前面在xml 的 标签中写返回类型 resultType 时,直接就是定义到某个实体类就行,但这种情况只适用于字段名称和程序中属性名相同的情况下,这种就是写起来方便

但如果是字段名称和属性名不同时,继续使用 resultType 就会报错,此时就要使用 resultMap 来配置映射

在一对一、一对多关系中可以使用 resultMap 映射并查询数
 

使用场景:实现程序中属性和表中字段映射的功能(当程序中的属性和表中的字段不一致时,可以强行的映射到一起)

我们更改一下userinfo中的属性:

 

 

 

或者使用as关键字(数据库重命名)

 

 当程序中的属性与数据库中的字段不一致时解决方案:

  1. 使用 resultMap 标签(在 mapper.xml 中定义);
  2. 使用数据库别名 as 重命名。

2.2 多表查询

(1)建立 Articalinfo 实体类:

@Data
public class Articleinfo  {
    private int id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private int uid;
    private int rcount;//阅读量
    private int state;
}

新增一个ArticleinfoVO实体类来帮助完成:

@Data
public class ArticleinfoVO extends Articleinfo implements Serializable {
    private String username;
}

(2)在 ArticleMapper 接口中写出通过用户id查询用户的方法

@Mapper
public interface ArticleMapper  {
    ArticleinfoVO getById(@Param("id") Integer id);
}

(3)在ArticleMapper.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.example.demo.mapper.ArticleMapper">

    <select id="getById" resultType="com.example.demo.eneity.vo.ArticleinfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id=a.uid
        where a.id=#{id}
    </select>
</mapper>

(4)生成测试方法

@SpringBootTest
class ArticleMapperTest {

    @Autowired
    private ArticleMapper articleMapper;


    @Test
    void getById() {
        ArticleinfoVO articleinfoVO = articleMapper.getById(1);
        System.out.println(articleinfoVO);
    }
}

我们发现:

 明明上面已经有结果了,但是下面的打印只有扩展字段,基类的字段去哪了?

 我们来梳理一下多表查询所经历的历程:

  1. 查询
  2. 打印

我们通过打点来看看是哪一步出现了错误:

我们可以得到:查询操作是没有问题的

所以问题出在了打印这里了

我们去查看字节码后发现

我使用的是Lombok的toString,而它只给我打印了一个拓展字段

这时候我们不需要Lombok的打印了,我们重写toString方法

在toString的时候加上父类的toString

 

 

 当存在Lombok的toString方法和用户的toString方法时,打印选择的是用户的方法!!用户大于一切

最终的一个实现:联表查询语句(left join/inner join)+XXXVO 解决。

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

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

相关文章

所有AI图都在这了

最近一直在玩AI生图&#xff0c;有点拔不出来了&#xff0c;喜欢生图的感觉&#xff0c;日积月累&#xff0c;已经有几千张图片了&#xff0c;想把这些图片都分享出来给大家欣赏&#xff0c;云盘、图片APP&#xff0c;感觉都不好用&#xff0c;最后熬夜码了一个属于自己的图片管…

(树) 剑指 Offer 68 - II. 二叉树的最近公共祖先 ——【Leetcode每日一题】

❓剑指 Offer 68 - II. 二叉树的最近公共祖先 难度&#xff1a;简单 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科 中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是…

2462. 雇佣 K 位工人的总代价

题目描述&#xff1a; 主要思路&#xff1a; 分别维护两个堆&#xff0c;取左右两边最小的那个。 class Solution { public:long long totalCost(vector<int>& costs, int k, int candidates) {priority_queue<int,vector<int>,greater<int>> ql…

清洗无效邮箱地址,让邮件营销更高效

作为一种低成本、高回报的营销手段&#xff0c;电子邮件营销因其传播效率高、营销范围广的特点被广泛应用。虽然现在短视频营销、搜索引擎营销、自媒体营销、内容营销等各种网络营销方式层出不穷。但是在整个网络营销宣传活动中&#xff0c;大多数企业还是会选择把邮件营销作为…

【Java从入门到大牛】File和IO流上篇

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Java从入门到大牛 &#x1f320; 首发时间&#xff1a;2023年8月9日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e…

《合成孔径雷达成像算法与实现》Figure3.5

clc clear all close all%参数设置 TBP 100; %时间带宽积 T 10e-6; %脉冲持续时间%参数计算 B TBP/T; %信号带宽 K B/T; …

如何简化大型网络服务提供商中的DDoS防护事宜

分布式拒绝服务&#xff08;DDoS&#xff09;攻击对服务提供商构成重大威胁&#xff0c;它们有可能破坏关键基础设施并扰乱业务运营。然而对于大型服务提供商而言实施和管理有效的DDoS防护解决方案可能非常复杂且成本高昂。 下面&#xff0c;火伞云将和大家一起探讨如何简化大型…

【云原生】kubernetes控制器deployment的使用

目录 ​编辑 1 Controller 控制器 1.1 什么是 Controller 1.2 常见的 Controller 控制器 1.3 Controller 如何管理 Pod 2 Deployment 2.1 创建 deployment 2.2 查看 deployment 2.3 扩缩 deployment 2.4 回滚 deployment 2.5 删除 deployment 1 Controller 控制器 …

idea如何上传项目到github(超详细)

idea如何上传项目到github 1、IDEA配置2、项目上传到本地仓库2.1、创建本地git仓库2.2、Add操作2.3、Commit操作 3、项目上传到Github4、拿到登录Github的token 1、IDEA配置 File-Settings-VersionControl-Git Git的安装路径下bin目录下的git.exe可执行文件 可以直接点 Gene…

【生成式AI】Diffusion Model 原理详解

Diffusion Model 【碎碎念】感觉Diffusion Model里面的数学公式太多了QwQ&#xff0c;所以自己稍微梳理一下。 我自己是听B站的课程&#xff1a;李宏毅课程听懂的&#xff0c;感觉讲得很清楚 概念模型 Diffusion Model的基本思想就是&#xff1a; 把一张图片通过 T T Tstep …

Redis类型检查与命令多态

Redis中用于操作键的命令基本上可以分为两种类型。 其中一种命令可以对任何类型的键执行&#xff0c;比如说DEL命令、EXPIRE命令 、RENAME命令、TYPE命令、OBJECT命令等。 举个例子&#xff0c;以下代码就展示了使用DEL命令来删除三种不同类型的键: # 字符串键 redis> SE…

实习碎碎念

话说实习一周多了&#xff0c;学到的比自学一个月都多~~~加油狗子你最棒&#xff01;&#xff01;&#xff01; 环境搭建坑死了 SSM框架环境配置 Ideamavenjdktomcatnavicat https://www.cnblogs.com/seigann/p/14528551.htmlhttps://www.cnblogs.com/seigann/p/14528551.h…

聚焦| 900万次点赞量 藏家绣娘直播大赛首秀引关注

义乌00后大学生驻村导师提交援藏教学成绩单 2023年7月30日&#xff0c;第三届全国“乡村振兴智创未来”巾帼共兴创业创新&#xff08;丹巴分赛区&#xff09;大赛暨“川府农博”试运行启动仪式在丹巴县高级中学体育馆举办。 本次比赛由金华市妇女联合会指导&#xff0c;中共丹…

C语言三子棋小游戏--数组的应用

注&#xff1a;在最后面&#xff0c;完整源码会以两种形式展现。在讲解时&#xff0c;以三个源文件的形式。 前言&#xff1a;三子棋&#xff0c;顾名思义&#xff0c;就是三个子连在一起就可以胜出。在本节我们要介绍的三子棋模式是这样子的&#xff1a;在键盘输入坐标&#x…

Python-OpenCV中的图像处理-物体跟踪

Python-OpenCV中的图像处理-物体跟踪 物体跟踪 物体跟踪 现在我们知道怎样将一幅图像从 BGR 转换到 HSV 了&#xff0c;我们可以利用这一点来提取带有某个特定颜色的物体。在 HSV 颜色空间中要比在 BGR 空间中更容易表示一个特定颜色。在我们的程序中&#xff0c;我们要提取的…

LAMMPS推出GUI界面,模拟从未如此简单

lammps一直没有编辑界面&#xff0c;对新手来说特别的不友好&#xff0c;不过&#xff0c;今年8月4号lammps推出了一款包含界面的版本。 运行效果如下图所示&#xff0c;这个版本带有独立的编辑界面&#xff0c;可以使用菜单新建或者打开in文件&#xff0c;也可以使用菜单运行…

python中 “”和“and”的区别

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 1、“&”和“and”有本质区别&#xff0c;属于不同类型的运行符号。& 是位运算&#xff1b;and 是逻辑运算。 2、首先是&&#xff1a;该运输符属于字符串的连接运算符&#xff0c;例如&#xff0c;“w“&”c…

FP独立站苦于投放广告?GG斗篷搞定难题!

在做FP独立站时&#xff0c;卖家常常面临各种难题。因为产品不是正品&#xff0c;因此广告很难过审。然而&#xff0c;为了获得利润&#xff0c;卖家总能找到适合的解决办法。以前&#xff0c;FP卖家常常使用SEO站群的方式&#xff0c;在搜索引擎上抢占免费流量&#xff0c;同时…

Linux-PG+postgres安装

一、PG数据库安装 1. 获取所需依赖包 wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/l/llvm5.0-devel-5.0.1-7.el7.x86_64.rpm wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/l/llvm5.0-5.0.1-7.el7.x86_64.rpm wge…

MES与ERP到底有什么不同?MES和ERP的区别

MES和ERP两款系统&#xff0c;在生产制造界早已经名声响亮&#xff0c;但至今还是有很多人分不清这两个系统究竟有什么区别&#xff0c;下面就来讲解一下。 要区分两者&#xff0c;首先就要弄清楚它们是什么。 MES系统 MES全称为制造执行系统&#xff08;Manufacturing Execu…