MyBatis实现数据库的CRUD

本文主要讲解使用MyBatis框架快速实现数据库中最常用的操作——CRUD。本文讲解的SQL语句都是MyBatis基于注解的方式定义的,相对简单。

Mybatis中#占位符和$拼接符的区别

“#”占位符

在使用MyBatis操作数据库的时候,可以直接使用如下SQL语句删除一条数据:

    @Delete("delete from user where id=5")
    public Integer deleteById();

这条SQL语句可以成功删除user表中id为5的用户,但是存在一个问题:硬编码。这条用于删除数据的SQL将删除的条件写死了只能删除id为5的用户,但假如说下一次需要删除id为6的用户就必须重新编写一条SQL,即使这两条SQL语句只是条件略有差别。这样不但会增加我们编码的工作,还会降低数据库的执行效率。为了解决这个问题,我们可以使用#占位符代替条件:

    @Delete("delete from user where id=#{id}")
    public Integer deleteById(Integer id);

使用#占位符,在SQL语句的删除条件中进行占位,这样编写SQL语句之后,就需要给deleteById方法传递需要删除的用户的id,在程序编译时,就会将这条SQL语句编译为一条预编译SQL

delete from user where id=?

然后再用方法中传递的参数id去对预编译SQL中的?进行参数绑定(将Java方法中的参数SQL语句中的占位符建立关联并赋值的操作),从而避免硬编码的问题,并且还可以提高SQL语句的执行效率。预编译SQL的好处此处不再赘述,有关预编译SQL的详情可以参考这篇文章:预编译SQL- 掘金。

“$”拼接符

和#占位符不同,$只是拼接符,是直接将参数值拼接在SQL中,并不能使SQL语句变成预编译SQL,所以说就算使用$拼接符可以解决SQL语句硬编码问题,但是还是存在SQL注入问题性能低下的问题(预编译SQL可以解决这些问题),所以说$拼接符使用十分少。但是当SQL语句中的表名和字段名需要动态变化的时候,就只能使用$拼接符,如:

select * from ${tablename}

这种动态的表名会使用$拼接符

Create

CRUD中的“C”操作是指create,create操作是在数据库中新增一条数据,通过MyBatis中的@Insert注解可以便捷的新增数据。当进行数据新增操作时,往往会涉及多个不同类型的属性。从数据组织和管理的角度出发,为了更好地维护数据的完整性和关联性,更方便的使用数据;通常会将这些相关属性封装为一个实体对象。这种实体对象的设计遵循面向对象编程的原则,以业务逻辑中的实际实体为蓝本,例如在用户管理系统中,用户相关的属性(如用户名、密码、姓名、年龄等)会被封装在一个User实体对象中。这个实体对象会作为参数传递给负责新增数据的方法,SQL中的占位符会获取对象中的属性来进行参数绑定

    @Insert("insert into user(id, username, password, name, age) " +
            "values (#{id}, #{username}, #{password}, #{name}, #{age})")
    public Integer insertUser(User user);

SQL语句中values中的值就是User对象中的属性,是#占位符从User对象中的属性中获取的。获取细节本文不做细究,但是#占位符中的参数和User对象属性建议相同(便于参数绑定)。

测试该方法:

    @Test
    public void testInsert() {
        User user = new User(null, "zhouyu", "123456", "周瑜", 23);
        Integer rows = userMapper.insertUser(user);
        System.out.println("影响的行数是:" + rows);
    }

(因为id字段是主键,并且自增,所以说不需要传递id的参数。)

原数据表:

测试结果:

如图所示,新增用户方法insertUser成功在数据库表中插入(新增)了一条新的用户数据,观察数据库表和返回值(影响的行数)可以发现新增方法成功了。

需要说明的是:用户的id是自增的,前面自测的时候创建了很多user,所以说id自增到了10,虽然删除了这些user,但是id也是从10开始自增的,所以说再次添加user,id从10自增,则变成11。

Read

CRUD中的“R”操作是指read,read操作是查询(读取)数据库中的数据,通过MyBatis中的@Select注解可以便捷的完成数据的查询:

    @Select("select * from user where username = #{username} and password = #{password}")
    public void selectUser(@Param("username")String username, @Param("password")String password);

此处的查询条件只有两个usernamepassword),只涉及到了两个字段(属性),所以说没有必要将属性封装到User对象中传递,可以直接传递;但是需要非常注意的是此处传递的是参数名#占位符绑定的也是参数名,但是在编译后方法形参列表中的参数名不会保留,只会保留参数的类型,而#占位符参数绑定是在编译后进行的,此时方法形参列表中有两个参数(此时只有类型了),#占位符无法根据参数名进行准确绑定,所以说就会报错。为了解决这个问题,需要在方法的形参之前添加@Param注解指定该参数的名字#占位符中也需要使用和@Param注解中相同的名字(不一定需要和形参名字一样,只需要和@Param注解中的名字一样即可),这样才可以正确参数绑定。但使用官方的SpringBoot框架,无需使用@Param注解,只要保证#占位符中的参数和方法的形参名相同即可,也可以完成参数绑定。(所以说建议#占位符中参数和实体类的属性名相同)。

测试方法:

    @Test
    public void testFind() {
        User user = userMapper.selectUser("liubei", "123456");
        System.out.println(user);
    }

 如图所示,根据usernamepassword成功查询到了对应的用户信息,并封装为了User实体对象,说明查找方法selectUser成功。

Update

CRUD的“U”是指update,update操作是更新数据库中的数据,通过MyBatis中的@Update注解可以便捷的完成数据的更新:

    @Update("update user set username=#{username}, password=#{password}, name=#{name}, age=#{age} where id=#{id}")
    public Integer updateUser(User user);

insert操作类似,由于需要更新的字段比较多,所以说需要将要更新的字段封装为对应实体对象,然后通过#占位符获取对象的属性,完成SQL语句的参数绑定需要注意的是,在insert操作中,因为用户的id是自增的,所以说不需要传递id属性,但是在update操作中,绝大部分情况都是需要根据id属性寻找需要更新的数据,大多数时候是需要传递id属性的,但是也需要根据具体情况而定。

测试方法:

    @Test
    public void testUpdate() {
        User user = new User(1, "liubei", "123456", "刘备", 25);
        Integer rows = userMapper.updateUser(user);
        System.out.println("影响的行数是:" + rows);
    }

测试前数据表:

测试结果:

如图所示,运行updateUser方法之后,发现id为1的用户被修改为了刘备,说明该修改方法成功修改了用户数据。

Delete

CRUD的“U”是指delete,delete操作是删除数据库中的数据,通过MyBatis中的@Delete注解可以便捷的完成数据的删除:

    @Delete("delete from user where id=#{id}")
    public Integer deleteById(Integer id);

在MyBatis中执行所有的DML语句都是有返回值的,是int类型,代表这条语句影响的记录数,通过测试方法来测试下这个删除方法:

原数据表:

测试方法:

    @Test
    public void testDelete() {
        Integer rows = userMapper.deleteById(5);
        System.out.println("影响的行数是:" + rows);
    }

我们看到#占位符确实将SQL语句变成了一条预编译SQL,并且这条SQL影响了一条记录。看看数据库中的变化: 

id为5的记录确实被删除了,说明deleteUser方法成功运行,从数据库中删除了一个用户。

总结

CRUD是数据库中的基本操作,是必须要会的技能,通过MyBatis框架,我们可以十分便捷的操作数据库,完成CRUD操作。

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

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

相关文章

微调神经机器翻译模型全流程

MBART: Multilingual Denoising Pre-training for Neural Machine Translation 模型下载 mBART 是一个基于序列到序列的去噪自编码器,使用 BART 目标在多种语言的大规模单语语料库上进行预训练。mBART 是首批通过去噪完整文本在多种语言上预训练序列到序列模型的方…

RTX 5090 加持,科研服务器如何颠覆 AI 深度学习构架?

RTX 5090作为英伟达旗舰级GPU,凭借Ada Lovelace架构,融合创新的SM多单元流处理器、第三代RT Core与第四代Tensor Core,打造出极为强劲的计算体系。其24GB GDDR6X显存搭配1TB/s带宽,能以极低延迟和超高吞吐量处理大规模张量数据&am…

【2025最新】机器学习类计算机毕设选题80套,适合大数据,人工智能

【2025最新】机器学习类型计算机毕设选题 1-10套 基于Spring Boot的物流管理系统的设计与实现 基于机器学习的虚假招聘信息的分析与预测 基于机器学习的影响数据科学家职业变动因素的分析与预测 基于Spring Boot的历史文物交流平台的设计与实现 基于机器学习的肥胖影响因素的分…

【PPTist】幻灯片放映

放映功能的代码都在 src/hooks/useScreening.ts,我们看一下 从当前页开始 放映的功能。 // 进入放映状态(从当前页开始) const enterScreening () > {enterFullscreen()screenStore.setScreening(true) }首先是 enterFullscreen()&#…

MySQL 16 章——变量、流程控制和游标

一、变量 在MySQL数据库的存储过程和存储函数中,可以使用变量来存储查询或计算的中间结果数据,或者输出最终的结果数据 在MySQL数据库中,变量分为系统变量和用户自定义变量 (1)系统变量 1.1.1系统变量分类 变量由…

T-SQL编程

目录 1、T-SQL的元素 1.1 标识符 1. 常规标识符 2. 分隔标识符 1.2 变量 1. 全局变量 2. 局部变量 1.3 运算符 1. 算数运算符 2. 赋值运算符 3. 位运算符 4. 比较运算符 5. 逻辑运算符 6. 字符串连接运算符 7. 一元运算符 8. 运算符的优先级和结合性 1.4 批处…

2024 China Collegiate Programming Contest (CCPC) Zhengzhou Onsite 基础题题解

L. Z-order Curve 思路:这题目说了,上面那一行,只有在偶数位才有可能存在1,那么一定存在这样的数,0 ,1,100, 10000,那么反之,我们的数列是行的二倍,因此会出现10,1000,100000这样的数&#xff0…

Unity2D初级背包设计后篇 拓展举例与不足分析

Unity2D初级背包设计中篇 MVC分层撰写(万字详解)-CSDN博客、 如果你已经搞懂了中篇,那么对这个背包的拓展将极为简单,我就在这里举个例子吧 目录 1.添加物品描述信息 2.拓展思路与不足分析 1.没有删除只有丢弃功能,所以可以添加垃圾桶 2.格…

vue(七) vue进阶

目录 第一课:Vue方法、计算机属性及侦听器 一、数组变化侦测 方法1:变更方法 方法2:替换一个数组 例子:小Demo:合并两个数组 二、计算属性 1.基础(不推荐) 2.使用计算属性来完成案例 3.使用函数的方…

Spring Boot 2 学习指南与资料分享

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域,Spring Boot 2 凭借其卓越的特性,为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2,以下这份精心…

YangQG 面试题汇总

一、交叉链表 问题: 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 解题思想: 双指针 备注:不是快慢指针,如果两个长度相…

fastapi 使用

参考: https://fastapi.tiangolo.com/zh/tutorial/first-steps/https://fastapi.tiangolo.com/zh/tutorial/first-steps/ FastAPI 用于基于标准 Python 类型提示使用 Python 构建 API,使用 ASGI 的标准来构建 Python Web 框架和服务器。所有简单理解&a…

2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本)

2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本),大家有什么好的也可以发一下看看

泛目录和泛站有什么差别

啥是 SEO 泛目录? 咱先来说说 SEO 泛目录是啥。想象一下,你有一个巨大的图书馆,里面的书架上摆满了各种各样的书,每一本书都代表着一个网页。而 SEO 泛目录呢,就像是一个超级图书管理员,它的任务就是把这些…

k8s基础(6)—Kubernetes-存储

Kubernetes-存储概述 k8s的持久券简介 Kubernetes的持久卷(PersistentVolume, PV)和持久卷声明(PersistentVolumeClaim, PVC)为用户在Kubernetes中使用卷提供了抽象。PV是集群中的一块存储,PVC是对这部分存储的请求。…

深度学习-卷积神经网络反向传播梯度公式推导

这篇文章非常棒,单样本单通道的反向传播梯度公式推导我都理解了。为了防止找不到原网页,所以特复制于此 参考: https://zhuanlan.zhihu.com/p/640697443

论文笔记(四十七)Diffusion policy: Visuomotor policy learning via action diffusion(下)

Diffusion policy: Visuomotor policy learning via action diffusion(下) 文章概括5. 评估5.1 模拟环境和数据集5.2 评估方法论5.3 关键发现5.4 消融研究 6 真实世界评估6.1 真实世界Push-T任务6.2 杯子翻转任务6.3 酱汁倒入和涂抹任务 7. 实际双臂任务…

C#学习笔记 --- 简单应用

1.operator 运算符重载:使自定义类可以当做操作数一样进行使用。规则自己定。 2.partial 分部类: 同名方法写在不同位置,可以当成一个类使用。 3.索引器:使自定义类可以像数组一样通过索引值 访问到对应的数据。 4.params 数…

汽车基础软件AutoSAR自学攻略(四)-AutoSAR CP分层架构(3) (万字长文-配21张彩图)

汽车基础软件AutoSAR自学攻略(四)-AutoSAR CP分层架构(3) (万字长文-配21张彩图) 前面的两篇博文简述了AutoSAR CP分层架构的概念,下面我们来具体到每一层的具体内容进行讲解,每一层的每一个功能块力求用一个总览图,外加一个例子的图给大家进…

【2024年华为OD机试】 (CD卷,100分)- 最大N个数与最小N个数的和(Java JS PythonC/C++)

一、问题描述 题目描述 给定一个数组,编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重。 说明: 数组中数字范围 [0, 1000]最大N个数与最小N个数不能有重叠,如有重叠,输入非法返回 -1输入非法返回 -1 …