Mybatis-特殊SQL的执行

1. 模糊查询

在MyBatis中进行模糊查询时,有以下三种常见的实现方式:


1.1. 错误示范

先来个准备操作,并做一个错误示例

根据姓名,模糊查询用户,(x小x)

更新数据表

SQLMapper.java

package com.sakurapaid.mybatis3.select.mapper;

import com.sakurapaid.mybatis3.select.bean.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface SQLMapper {
    // 根据姓名,模糊查询用户,(x小x)
    List<User> findUserByName(@Param("name") String name);
}

SQLMapper.xml、

这是错误示例,我是——like '%#{name}%'

<?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.sakurapaid.mybatis3.select.mapper.SQLMapper">
    <!--根据姓名,模糊查询用户,(x小x)-->
    <select id="findUserByName" resultType="com.sakurapaid.mybatis3.select.bean.User">
        select * from user where name like '%#{name}%'
    </select>
</mapper>

测试输出

package com.sakurapaid.mybatis3.select.test;

import com.sakurapaid.mybatis3.select.bean.User;
import com.sakurapaid.mybatis3.select.mapper.SQLMapper;
import com.sakurapaid.mybatis3.select.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.List;

public class SQLTest {
    @Test
    public void test(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        List<User> out = mapper.findUserByName("小");
        for (User user : out) {
            System.out.println(user);
        }
    }
}

记住我上面的SQL语句,编译时就会报错

在 SQL 查询语句中使用了 MyBatis 的动态参数 #{name},但在对应的 mapper 映射配置中未正确设置该参数,导致在执行 SQL 查询时,JDBC 无法识别并适配这个参数,从而抛出了“Parameter index out of range”的异常。


所以,#{ }虽然常用,但并不是万能的,遇到模糊查询还是要适当调整的,也就引出了下面要讲到的三种在mybatis中模糊查询的方法


1.2. 方式一:使用#{}占位符

#{ }占位符结合contact函数

<select id="findUserByName" resultType="com.sakurapaid.mybatis3.select.bean.User">
        select * from user where name like concat('%',#{name},'%')
    </select>

解释
这里使用了#{}占位符来传递参数name。MyBatis会将#{name}替换为预编译语句中的参数,并自动为其加上单引号。通过concat函数将通配符%与参数值拼接成完整的模糊查询条件。这种方式能够防止SQL注入,因为参数值是经过预编译处理的,且无需手动添加单引号。

测试输出:

测试语句还是最上面那个


1.3. 方式二:使用${}变量替换

直接使用${ },但记得要加引号

<select id="testMohu" resultType="User">
    select * from user where name like '%${name}%'
</select>

解释
这种方式使用${}变量替换符来嵌入参数name的值。${name}会被直接替换为变量的值,不会添加任何额外的引号。因此,如果传入的name值为,生成的SQL语句将是select * from t_user where username like '%小%'。这种方式虽然简洁,但存在SQL注入的风险,因为变量值未经预编译直接插入到SQL语句中。除非能确保传入值的安全性,否则不建议使用此方式。

测试输出:

测试语句还是最上面那个


1.4. 方式三:手动添加双引号

最推荐的,也是实际开发中最常用的

<select id="testMohu" resultType="User">
    select * from user where name like "%"#{name}"%"
</select>

解释
这种方式结合了#{}占位符的预编译安全性与手动添加双引号来包裹通配符和参数。虽然看起来与方式一类似,但这里的#{name}被双引号包围,使得MyBatis在替换参数时,生成的SQL语句中参数值仍被双引号包围,形如select * from user where name like "%'小'%"


2. 批量删除

要使用${ },而非#{ },来避免自动添加单引号


定义接口方法

// 批量删除用户
int deleteMore(@Param("ids") String ids);

编写Mapper XML映射文件

看清楚我这个错误示范

<delete id="deleteMore">
    delete from user where id in (#{ids})
</delete>

测试输出

@Test
public void test(){
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
    int i = mapper.deleteMore("4,5,6");
    System.out.println(i);
}

不能使用#{ },只能使用${ }

<delete id="deleteMore">
    delete from user where id in (${ids})
</delete>

受影响行数1,因为我表里的id值只有1-4,就删除了4,


3. 动态设置表名

也要使用${ },而非#{ },来避免自动添加单引号


定义接口方法

/**
 * 动态设置表名,查询所有的用户信息
 * @param tableName
 * @return
 */
List<User> getAllUser(@Param("tableName") String tableName);

编写Mapper XML映射文件

看清楚我这个错误示范

<select id="getAllUser" resultType="com.sakurapaid.mybatis3.select.bean.User">
      select * from #{tableName}
</select>

测试输出

@Test
public void test(){
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
    List<User> allUser = mapper.getAllUser("user");
    allUser.forEach(System.out::println);
}

不能使用#{ },只能使用${ }

<select id="getAllUser" resultType="com.sakurapaid.mybatis3.select.bean.User">
      select * from ${tableName}
</select>


4. 添加功能获取自增的主键

在数据库应用开发中,使用自增主键是一种常见且实用的设计策略。自增主键字段的值会自动递增,每当插入一条新记录时,数据库系统会为其自动分配一个唯一的、递增的整数值作为主键。

场景一:简化数据插入操作

场景描述: 当需要在数据库中创建新的实体记录(如用户、订单、文章等)时,开发者通常需要为这些记录指定一个唯一的标识符。使用自增主键可以免去手动为每条新记录生成唯一ID的复杂性。

使用自增主键: 开发者只需关注其他非主键字段的数据填充,插入操作时无需指定主键值。数据库系统会自动为新插入的记录生成下一个自增主键值。例如,在创建新用户时,只需提供用户名、密码、邮箱等信息,主键ID由数据库自动生成。

场景二:确保数据唯一性

场景描述: 在多用户并发环境下,如果没有有效的机制保证主键的唯一性,可能会出现主键冲突,导致数据插入失败。自增主键能有效防止此类问题。

使用自增主键: 数据库系统内部对自增主键的管理确保了每次插入新记录时主键值的唯一性。即使在高并发场景下,不同用户同时尝试插入记录,也不会产生相同的主键值,从而避免数据冲突。


定义接口方法

// 添加用户
int insertUser(User user);

编写Mapper XML映射文件

useGeneratedKeys="true":指示MyBatis在执行INSERT操作后使用JDBC的getGeneratedKeys()方法获取数据库自动生成的主键值。

keyProperty="id":指定获取到的自增主键值应被赋给传入映射语句的参数对象(如User)的特定属性(如id),实现主键值的自动回填。

两者结合使用,确保在插入新记录后,自动生成的主键能被无缝地赋给对应的Java对象属性,简化了主键管理与后续业务逻辑的处理。

<!--useGeneratedKeys:设置使用自增的主键-->
<!--keyProperty:因为增删改有统一的返回值是受影响的行数,
因此只能将获取的自增的主键放在传输的参数user对象的某个属性中-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into user values (null,#{name},#{age},#{sex});
</insert>

测试输出

@Test
public void test(){
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
    User user = new User(null, "李四", 23, "男");
    int i = mapper.insertUser(user);
    if (i > 0) {
        System.out.println("插入成功");
        System.out.println(user);
    } else {
        System.out.println("插入失败");
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python 进程、线程、协程基本使用

1、进程、线程以及协程【1】进程概念【2】线程的概念线程的生命周期进程与线程的区别 【3】协程(Coroutines) 2、多线程实现【1】threading模块【2】互斥锁【3】线程池【4】线程应用 3、多进程实现4、协程实现【1】yield与协程【2】asyncio模块【3】3.8版本【4】aiohttp 1. 并发…

《C++工程方向面试记录》

此系列&#xff0c;是本人免费提供的&#xff0c;大厂面试模拟&#xff0c;经本人同意后发出。如要申请&#xff0c;请查看《大厂面试模拟&#xff08;免费&#xff09;》 面试者画像&#xff1a; 本硕中部985&#xff0c;工作2-3年&#xff0c;本硕均非计算机专业。毕业后一直…

南京观海微电子---Vitis HLS设计流程介绍——Vitis HLS教程

1. 传统的FPGA设计流程 传统的RTL设计流程如下图所示&#xff1a; 传统的FPGA RTL设计流程主要是采用VHDL、VerilogHDL或System Verilog进行工程的开发&#xff0c;同时也是通过硬件描述语言来编写测试案例&#xff08;Test Bench&#xff09;对开发的工程进行仿真验证。 随后…

SpringBoot接收参数的方式

Get 请求 1.1 以方法的形参接收参数 1.这种方式一般适用参数比较少的情况 RestController RequestMapping("/user") Slf4j public class UserController {GetMapping("/detail")public Result<User> getUserDetail(String name,String phone) {log.…

二维码门楼牌管理应用平台建设:实现民主参与的新途径

文章目录 前言一、二维码门楼牌管理应用平台的兴起二、投票表决功能的实现三、居民参与度的提升四、面临的挑战与前景展望 前言 在数字化时代&#xff0c;二维码技术的应用已经渗透到我们生活的方方面面。近期&#xff0c;二维码门楼牌管理应用平台的建设成为了社区治理的一大…

leecode 331 |验证二叉树的前序序列化 | gdb 调试找bug

计算的本质是数据的计算 数据的计算需要采用格式化的存储&#xff0c; 规则的数据结果&#xff0c;可以快速的按照指定要求存储数据 这里就不得不说二叉树了&#xff0c;二叉树应用场景真的很多 本题讲的是&#xff0c;验证二叉树的前序序列化 换言之&#xff0c;不采用建立树的…

Kubernetes(K8S)学习(二):K8S常用组件

K8S常用组件 一、 Controllers1、ReplicationController(RC)2、ReplicaSet(RS)3、Deployment 二、Labels and Selectors三、Namespace&#xff08;命名空间&#xff09;1、简介2、测试2.1、创建namespace2.2、创建pod 四、Network1、集群内&#xff1a;同一个Pod中的容器通信2、…

数据挖掘|贝叶斯分类器及其Python实现

分类分析|贝叶斯分类器及其Python实现 0. 分类分析概述1. Logistics回归模型2. 贝叶斯分类器2.1 贝叶斯定理2.2 朴素贝叶斯分类器2.2.1 高斯朴素贝叶斯分类器2.2.2 多项式朴素贝叶斯分类器 2.3 朴素贝叶斯分类的主要优点2.4 朴素贝叶斯分类的主要缺点 3. 贝叶斯分类器在生产中的…

力扣刷题Days29-第二题-70.爬楼梯(js)

只有学习&#xff0c;没有自己的思路解题哈哈哈 1&#xff0c;题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 2&#xff0c;代码 这种解法的本质是斐波那契数列 /*** param {number} n* re…

关于积分敛散性的这道考研数二真题,好多辅导资料都没有讲清楚!

考研数学二 2024 年真题的第 7 题是关于积分敛散性判别的&#xff0c;但是&#xff0c;细心的同学会发现&#xff0c;对于这道题目&#xff0c;某些考研机构给出的解析资料其实并没有讲清楚具体解题方法&#xff0c;甚至还存在错误&#xff0c;有关这道题目的详细解析&#xff…

分布式数据库技术的演进和发展方向

前言 这些年大家都在谈分布式数据库&#xff0c;各大企业也纷纷开始做数据库的分布式改造。那么&#xff0c;所谓的分布式数据库到底是什么&#xff1f;采用什么架构&#xff1f;优势在哪&#xff1f;为什么越来越多企业选择它&#xff1f;分布式数据库技术会向什么方向发展&a…

区块链+AI,AG与Speedy联合Sui为收藏品打造数字身份

Speedy Comics&#xff08;PopCon Me的制片方&#xff09;和AGS&#xff08;一家由AI驱动的收藏品认证服务提供商&#xff09;将利用Sui来安全地托管证书&#xff0c;以证明验证过的流行文化收藏品的所有权和起源。从稀有的宝可梦卡到星球大战道具的收藏品&#xff0c;购买者可…

【分布式事务】Seata 简介

文章目录 1.分布式事务解决方案之两阶段提交协议2.Seata 简介&#xff08;两阶段提交协议的演变&#xff09;3.Seata 术语 1.分布式事务解决方案之两阶段提交协议 2PC&#xff0c;即两阶段提交协议&#xff08;Two-Phase Commit&#xff09;&#xff0c;是分布式系统中保证事务…

拦截器未生效的问题

记录一下自己出现的一个问题 配置好拦截器后 protected void addInterceptors(InterceptorRegistry registry) {log.info("开始注册自定义拦截器...");registry.addInterceptor(jwtTokenUserInterceptor).addPathPatterns("/**").excludePathPatterns(&q…

机器学习周记(第三十三周:文献阅读-时空双通路框架)2024.3.25~2024.3.31

目录 摘要 ABSTRACT 1 论文信息 1.1 论文标题 1.2 论文摘要 1.3 论文模型 1.3.1 Spatial Encoder&#xff08;空间编码器&#xff09; 1.3.2 Temporal Encoder&#xff08;时间编码器&#xff09; 2 相关代码 摘要 本周阅读了一篇运用GNN进行时间序列预测的论文。论文…

【论文阅读】UniLog: Automatic Logging via LLM and In-Context Learning

注 由于其公司的保密政策&#xff0c;本文没有公开源代码&#xff0c;数据是公开的。 文章目录 摘要一、介绍二、背景和动机2.1、日志语句生成2.2、大语言模型2.3、上下文学习&#xff08;In-Context Learning&#xff0c;ICL) 三、UNILOG3.1、模型骨干3.2、提示策略3.2.1、提…

大龄程序员的2024年3月总结:鸿蒙,发起GDE申请,金石计划获奖,月榜,技术文章

大家好&#xff0c;我是老A&#xff0c;一名工作十年的安卓开发&#xff1b; 又到了月末写总结的时候了&#xff0c;看过我文章的朋友应该会发现我没有写2月的总结&#xff0c;因为2月有春节假期&#xff0c;2月大部分时间都是在假期中度过的&#xff0c;所以就没有写2月总结&…

瓷砖通铺选择亮面还是哑光?了解这6点不难选。福州中宅装饰,福州装修

选择瓷砖通铺亮面还是哑光&#xff0c;可以从多个角度来考虑&#xff1a; ①空间感觉 亮面瓷砖通常会使空间看起来更加宽敞和明亮&#xff0c;而哑光瓷砖则给人大气、稳重的感觉。如果希望让空间显得更加宽敞&#xff0c;亮面瓷砖是一个不错的选择。 ②清洁与维护 亮面瓷砖更…

KNN算法 | K近邻:KD Tree、球树、KNN数据下采样策略

目录 一. KNN算法实现方式1. 蛮力实现(brute)2. KD树(kd_tree)3. 球树(ball_tree) 二. KD Tree算法1. 构建方式2. KD Tree 查找最近邻 三. 球树(Ball Tree)1. 构建方式 四. KNN评价1. 优点2. 缺点 五. 延申1. KNN数据下采样策略策略1策略2策略3策略4 Condensed Nearest Neighbo…

loadbalancer 引入与使用

在消费中pom中引入 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> 请求调用加 LoadBalanced 注解 进行服务调用 默认负载均衡是轮训模式 想要切换…