MyBatis查询数据库(3)(一)

简介: MyBatis查询数据库(3)

一、查询操作🍭

1、单表查询🍉

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

UserController 实现代码如下:


//url 路径名直接全部小写即可
    @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>

Ⅰ、参数占位符 #{} 和 ${}🍓

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

预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使用 PreparedStatement 的 set 方法来赋值。直接替换:是MyBatis 在预处理 时,∗∗就会把{} 时,**就会把 时,就会把{} 替换成变量的值。**

上面代码我们使用的是${},去传递Integer(整数)类型的参数时,是没有问题的,但如果传递的是String类型的话,程序就会报错。

image.png

下面我们通过 根据用户名查询用户(getUserByName)来看看

image.png

这就直接报错了,说是没有admin这个用户,这是因为${}是直接替换值(不会管你是什么类型,都直接替换),而SQL语句中字符串需要使用单引号,这就会查询不到,报错。

image.png

正确SQL:

image.png

两者区别总结:

1、``#{}:安全参数占位符

  • #{}是MyBatis的预编译语句中的参数占位符,用于传递参数值。它会自动进行参数值的类型转换和防止SQL注入攻击。
  • 在使用#{}时,MyBatis会将参数值通过JDBC的PreparedStatement接口进行预编译,参数值会被当做字符串类型处理,然后由JDBC驱动来负责将其转换成对应的数据库类型,这样可以避免SQL注入问题。
  • 例子:SELECT * FROM users WHERE id = #{userId}

2、``${}:字符串替换占位符

  • 是字符串替换占位符,用于直接将参数的值替换到SQL语句中。在使用{}是字符串替换占位符,用于直接将参数的值替换到SQL语句中。在使用是字符串替换占位符,用于直接将参数的值替换到SQL语句中。在使用{}时,参数值会被直接替换进SQL语句中,不会进行预编译或类型转换。
  • 由于直接替换参数值到SQL语句中,可能存在SQL注入的风险,因此不建议在动态SQL中使用{}直接替换参数值到SQL语句中,可能存在SQL注入的风险,因此不建议在动态SQL中使用直接替换参数值到SQL语句中,可能存在SQL注入的风险,因此不建议在动态SQL中使用{}来传递用户输入的参数。
  • 例子:SELECT * FROM users WHERE id = ${userId}

那这为什么还有${}去传递参数呢?全部使用#{}不是更好?

Ⅱ、${}优点🍓

image.png

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

UserMapper接口:


//根据id查询用户 并且进行排序
    List getAllByOrder(@Param("order") String order);

UserMapper.xml:


<select id="getAllByOrder" resultType="com.example.ssmdemo1.entity.Userinfo">
        select * from userinfo order by id ${order}
select>

单元测试:


@Test
    void getAllByOrder() {
        List list = userMapper.getAllByOrder("asc");
        System.out.println(list);
    }

单元测试成功:

image.png

Ⅲ、SQL 注入问题 🍓

UserMapper接口:


Userinfo login(@Param("username")String username,@Param("password")String password);

UserMapper.xml:


<select id="login" resultType="com.example.ssmdemo1.entity.Userinfo">
        select *from userinfo where usernaem='${username}' and password='${password}'
select>

因为${}是直接引用,所以我们加上了单引号。 这样就和使用#{}是一样的了

单元测试:


@Test
    void login() {
        String username="2";
        String password="2";
        Userinfo userinfo=userMapper.login(username,password);
        System.out.println("用户登录"+(userinfo==null?"失败":"成功"));
    }

可以看到此时用户是登录成功的:

image.png

但是这样写有SQL注入的风险,我们修改代码如下,然后运行代码


@Test
    void login() {
        String username="2";
        String password="'or 1 ='1";
        Userinfo userinfo=userMapper.login(username,password);
        System.out.println("用户登录"+(userinfo==null?"失败":"成功"));
    }

单元测试:

image.png

可以看到上面单元测试失败了,但仔细看,是因为返回了5个Userinfo对象,但我只需要接收一个

所以报错了,如果接受的是List

UserMapper接口:


List login(@Param("username")String username, @Param("password")String password);

单元测试:


@Test
    void login() {
        String username="2";
        String password="' or 1='1";
        List userinfo=userMapper.login(username,password);
        System.out.println("用户登录"+(userinfo==null?"失败":"成功"));
    }

单元测试成功:

image.png

可以看到这是非常可怕的,居然把我所有用户信息返回了(数据库中一共有五个用户),也就是说,你想使用哪个用户登录就可以使用哪个用户登录。

如果使用#{},可能存在这个问题吗?


<select id="login" resultType="com.example.ssmdemo1.entity.Userinfo">
        select *from userinfo where username=#{username} and password=#{password}
select>

单元测试失败:

image.png

结论:用于查询的字段,尽量使用 #{} 预查询的方式,而需要传递关键字时,使用${}

Ⅳ、like查询🍓

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

UserMapper接口:


List<Userinfo> getListByName(@Param("username")String username);

UserMapper.xml:


<select id="getListByName" resultType="com.example.ssmdemo1.entity.Userinfo">
        select * from userinfo where username like '%#{username}%'
select>

单元测试:


@Test
    void getListByName() {
        String username="n";
        List list=userMapper.getListByName(username);
        System.out.println("list:"+list);
    }

运行报错:

image.png

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


select * from userinfo where username like '%'n'%'

我们替换${}试试:

image.png

但是前面说了使用有SQL注入的风险,所有这是不能直接使用 {}有SQL注入的风险,所有这是不能直接使用 SQL注入的风险,所有这是不能直接使用 {},可以考虑使用 mysql 的内置函数 concat() 来处理,实现代码如下:


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

单元测试成功:

image.png

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

MyBatis查询数据库(3)(二)https://developer.aliyun.com/article/1393185


相关文章
|
5天前
|
XML Java 数据库连接
Mybatis一对一,一对多关联查询
## MyBatis一对一、一对多关联查询详解 MyBatis是一款优秀的持久层框架,提供了灵活的SQL映射功能,支持复杂的数据库操作。本文将详细介绍MyBatis中一对一和一对多关联查询的实现。 ### 一对一关联查询 一对一关联关系指的是一个表中的一条记录与另一个表中的一条记录相关联。例如,一个用户有一个地址信息。 #### 数据库表设计 假设有两个表:`user`和 `address`。 ``` CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(50) ); CREATE TABLE address
27 18
|
3天前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
45 6
|
3天前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
14 2
|
3天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
42 0
|
1月前
|
XML Java 数据库连接
Mybatis实现RBAC权限模型查询
通过对RBAC权限模型的理解和MyBatis的灵活使用,我们可以高效地实现复杂的权限管理功能,为应用程序的安全性和可维护性提供有力支持。
62 5
|
2月前
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
415 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
1月前
|
存储 缓存 网络协议
数据库执行查询请求的过程?
客户端发起TCP连接请求,服务端通过连接器验证主机信息、用户名及密码,验证通过后创建专用进程处理交互。服务端进程缓存以减少创建和销毁线程的开销。后续步骤包括缓存查询(8.0版后移除)、语法解析、查询优化及存储引擎调用,最终返回查询结果。
36 6
|
1月前
|
SQL Java 数据库连接
spring和Mybatis的各种查询
Spring 和 MyBatis 的结合使得数据访问层的开发变得更加简洁和高效。通过以上各种查询操作的详细讲解,我们可以看到 MyBatis 在处理简单查询、条件查询、分页查询、联合查询和动态 SQL 查询方面的强大功能。熟练掌握这些操作,可以极大提升开发效率和代码质量。
109 3
|
2月前
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
54 1
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
1月前
|
SQL JavaScript 程序员
数据库LIKE查询屡试不爽?揭秘大多数人都忽视的秘密操作符!
本文分析了因数据库中的不可见空白字符导致的数据查询问题,探讨了问题的成因与特性,并提出了使用 SQL 语句修复问题的有效方案。同时,总结了避免类似问题的经验和注意事项。
39 0