MyBatis实现数据库的CRUD

devtools/2025/1/15 7:31:50/

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

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

“#”占位符

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

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

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

java">    @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中的占位符会获取对象中的属性来进行参数绑定

java">    @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对象属性建议相同(便于参数绑定)。

测试该方法:

java">    @Testpublic 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注解可以便捷的完成数据的查询:

java">    @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注解,只要保证#占位符中的参数和方法的形参名相同即可,也可以完成参数绑定。(所以说建议#占位符中参数和实体类的属性名相同)。

测试方法:

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

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

Update

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

java">    @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属性的,但是也需要根据具体情况而定。

测试方法:

java">    @Testpublic 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注解可以便捷的完成数据的删除:

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

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

原数据表:

测试方法:

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

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

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

总结

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


http://www.ppmy.cn/devtools/150616.html

相关文章

宁德时代C++后端开发面试题及参考答案

请阐述面向对象的三大特性。 面向对象编程有三大特性,分别是封装、继承和多态。 封装是指将数据和操作数据的方法绑定在一起,对数据的访问和操作进行限制。这样做的好处是可以隐藏对象的内部细节,只暴露必要的接口给外部。例如,我们可以把一个汽车类的内部引擎状态、速度等…

使用 Docker 部署 Java 项目(通俗易懂)

目录 1、下载与配置 Docker 1.1 docker下载(这里使用的是Ubuntu,Centos命令可能有不同) 1.2 配置 Docker 代理对象 2、打包当前 Java 项目 3、进行编写 DockerFile,并将对应文件传输到 Linux 中 3.1 编写 dockerfile 文件 …

《自动驾驶与机器人中的SLAM技术》ch9:自动驾驶车辆的离线地图构建

目录 1 点云建图的流程 2 前端实现 2.1 前端流程 2.2 前端结果 3 后端位姿图优化与异常值剔除 3.1 两阶段优化流程 3.2 优化结果 ① 第一阶段优化结果 ② 第二阶段优化结果 4 回环检测 4.1 回环检测流程 ① 遍历第一阶段优化轨迹中的关键帧。 ② 并发计算候选回环对…

Vmware虚拟机centos扩展硬盘空间

一,调整硬盘大小 关闭虚拟机后才可以调整,否则 扩展 按钮是灰色的 扩展后,会弹出如下提示: 二,系统内部扩展 1. 知识铺垫 如果熟悉 Part(分区)、PV(物理卷)、VG(卷组)、LV(逻辑…

flutter R库对图片资源进行自动管理

项目中对资源的使用是开发过程中再常见不过的一环。 一般我们在将资源导入到项目中后,会通过资源名称来访问。 但在很多情况下由于我们疏忽输入错了资源名称,从而导致资源无法访问。 所以,急需解决两个问题: 资源编译期可检查可方…

Unity WebGL:本机部署,运行到手机

Unity WebGL 简单介绍一下Unity WebGL的技术方案,在WebGL平台出包后,Unity的运行时C/C代码是通过Emscripten编译成了WebAssembly/Wasm;游戏逻辑部分的C#代码是先通过il2cpp转成C再编译转成的Wasm,Unity程序就就可以在支持WebAsse…

HTTP 范围Range请求

引言 在现代Web应用中,HTTP范围请求是一种重要的技术,允许客户端请求资源的部分内容,而不是整个资源。这对于大型文件的传输尤其有用,如视频流、断点续传下载等。本文将深入探讨HTTP范围请求的工作原理、实现方法和应用场景。 H…

MTK6768 Android13 亮度条均匀调节实现

文章目录 需求:问题现象:需求实现疑难问题点:相关资源修改的文件调试技巧具体需求实现去除亮度弹框设置去掉跳转逻辑SystemUI亮度条长按跳转屏蔽 实现亮度均匀调节PhoneWindowManager.javaBrightnessUtils convertLinearToGammaFloatBrightne…