当前位置: 首页 > news >正文

MyBatis查询数据库(2)

目录

前言🍭

一、增删查改操作

1、查

Ⅰ、mapper接口:

Ⅱ、UserMapper.xml 查询所有用户的具体实现 SQL:

Ⅲ、进行单元测试

2、增、删、改操作

Ⅰ、增

添加用户

添加用户并且返回自增 id

Ⅱ、改

根据id修改用户名

开启 MyBatis sql 日志打印

Ⅲ、删

二、在单元测试时不污染数据库


前言🍭

❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客

上篇我们写了一个简单的根据id进行查询,知道了如何去进行查询,下面来仔细讲讲增删改查操作。

一、增删查改操作

下面操作会使用到Spring Boot单元测试,可以先看:

Spring Boot单元测试_spring boot 单元测试_冷兮雪的博客-CSDN博客

1、查

查询所有的用户:

Ⅰ、mapper接口:

package com.example.ssmdemo1.mapper;import com.example.ssmdemo1.entity.Userinfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;@Mapper//需要添加 @Mapper 注解
public interface UserMapper {/*** 根据用户id查询用户信息* @param id* @return*/Userinfo getUserById(@Param("id") Integer id);//查询所有的用户List<Userinfo> getAll();
}

Ⅱ、UserMapper.xml 查询所有用户的具体实现 SQL:

使用$进行传递参数可能会SQL注入,所以大部分情况下是使用#的 

<?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.ssmdemo1.mapper.UserMapper"><select id="getUserById" resultType="com.example.ssmdemo1.entity.Userinfo">select * from userinfo where id=${id}</select><select id="getAll" resultType="com.example.ssmdemo1.entity.Userinfo">select * from userinfo</select>
</mapper>

Ⅲ、进行单元测试

在UserMapperTest中就有了getAll的测试代码:

添加单元测试业务逻辑 

package com.example.ssmdemo1.mapper;import com.example.ssmdemo1.entity.Userinfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest//1、表明当前单元测试是运行在Spring Boot环境中的
class UserMapperTest {//2、注入测试对象@Autowiredprivate UserMapper userMapper;@Testvoid getUserById() {//3、添加单元测试的业务代码Userinfo userinfo=userMapper.getUserById(1);System.out.println(userinfo);//判断1是否等于2 简单断言Assertions.assertEquals("admin",userinfo.getUsername());}@Testvoid getAll() {List<Userinfo> list=userMapper.getAll();Assertions.assertEquals(1,list.size());//断言判断list集合里面是否只有一条数据,即查询数据库中只有一个用户}
}

 测试正确:

 如果我们没有设置resultType,则 MyBatis无法自动将查询结果映射到Java对象,这就会导致单元测试失败并报错。

2、增、删、改操作

与查询操作都是一样的,只是使用的标签不一样:

  • <insert>标签:插入语句
  • <update>标签:修改语句
  • <delete>标签:删除语句

Ⅰ、增

添加用户

①、在接口(UserMapper)中声明方法

    Integer add(Userinfo user);

②、UserService

public Integer getAdd(Userinfo user) {return userMapper.add(user);}

③、在xml中提供实现

<insert id="add">insert into userinfo(username,password) values(#{username},#{password})
</insert>

#{} 进行赋值使用的是对象中的属性。

注意:对应的不是数据库的字段,而是程序类中的属性。

④、controller 实现代码:

@RequestMapping(value = "/add",method = RequestMethod.POST)public Integer add(@RequestBody Userinfo user){return userService.getAdd(user);}

⑤、单元测试

@Testvoid add() {//伪代码,构建对象并设置对应的值//本来是前端传值过来Userinfo userinfo=new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("123456");//调用mybatis 添加方法执行添加操作int result=userMapper.add(userinfo);Assertions.assertEquals(1,result);}

 单元测试成功,可以去看数据库也添加了一条数据

但是如果我们去获取这个用户的id,就会报空指针异常:

添加用户并且返回自增 id

 如果我们想在添加用户的时候同时去获取他的id,具体实现如下:

①、在接口(UserMapper)中声明方法

Integer addGetid(Userinfo user);

②、UserService

public Integer addGetid(Userinfo user) {return userMapper.addGetid(user);}

③、在xml中提供实现

<insert id="addGetid" useGeneratedKeys="true" keyProperty="id">insert into userinfo(username,password) values(#{username},#{password})
</insert>
  • useGeneratedKeys:这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
  • keyColumn:设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列 不是表中的第⼀列的时候,是必须设置的。如果⽣成列不止⼀个,可以用逗号分隔多个属性 名称。
  • keyProperty:指定能够唯⼀识别对象的属性,MyBatis会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止⼀个,可以⽤逗号分隔多个属性名称。

④、controller 实现代码:

 @RequestMapping(value = "/add2", method = RequestMethod.POST)public Integer add2(@RequestBody Userinfo user) {userService.addGetid(user);return user.getId();}

⑤、单元测试

@Testvoid addGetid() {//伪代码,构建对象并设置对应的值//本来是前端传值过来Userinfo userinfo=new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("123456");//调用MyBatis 添加方法执行添加操作 返回受影响的行数int result=userMapper.addGetid(userinfo);int id=userinfo.getId();//得到自增id(MyBatis自动赋值)System.out.println("id:"+id);Assertions.assertEquals(1,result);}

 一样的代码,就一行代码不同

Ⅱ、改

根据id修改用户名

①、在接口(UserMapper)中声明方法

/*** 修改用户* @param userinfo* @return*/Integer upUserName(Userinfo userinfo);

②、在xml中提供实现

<update id="upUserName">update userinfo set username=#{username} where id=#{id}
</update>

③、单元测试

将之前添加的张三修改成为李四

@Testvoid upUserName() {// 构建测试数据Userinfo userinfo = new Userinfo();userinfo.setId(9);userinfo.setUsername("李四");int result = userMapper.upUserName(userinfo);System.out.println("修改:" + result);Assertions.assertEquals(1, result);}

修改成功: 

如果我们需要在控制台看到SQL语句,需要去配置文件进行配置,因为这默认是隐藏MyBatic生成SQL语句的细节

开启 MyBatis sql 日志打印

①、添加配置文件

# 开启 mybatis sql 日志打印
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.example.demo=debug

②、重新运行单元测试

@Testvoid upUserName() {// 构建测试数据Userinfo userinfo = new Userinfo();userinfo.setId(9);userinfo.setUsername("张三");int result = userMapper.upUserName(userinfo);System.out.println("修改:" + result);Assertions.assertEquals(1, result);}

 执行成功:

结论: 可以看到这个就是jdbc链接,这个SQL写法也是jdbc的写法,也就是说mybatis是基于jdbc的,MyBatis使用了JDBC来与数据库进行交互,它也简化了JDBC的使用,提供了更方便的数据库访问方式。。

建议大家在开发阶段是开启SQL的打印,可以更好的帮助你找到错误。

Ⅲ、删

①、在接口(UserMapper)中声明方法

int delById(@Param("id") Integer id);

②、在xml中提供实现

<delete id="delById">delete from userinfo where id=#{id}
</delete>

 ③、单元测试

将id为9的用户删除:

@Testvoid delById() {int id=9;int result=userMapper.delById(id);System.out.println("删除:"+result);Assertions.assertEquals(1,result);}

删除成功: 

二、在单元测试时不污染数据库

在需要的地方添加注解:@Transactional(就可以修饰方法也可以修饰类)

 

 

相关文章:

MyBatis查询数据库(2)

目录 前言&#x1f36d; 一、增删查改操作 1、查 Ⅰ、mapper接口&#xff1a; Ⅱ、UserMapper.xml 查询所有用户的具体实现 SQL&#xff1a; Ⅲ、进行单元测试 2、增、删、改操作 Ⅰ、增 添加用户 添加用户并且返回自增 id Ⅱ、改 根据id修改用户名 开启 MyBatis …...

Jenkins构建完成后发送消息至钉钉

钉钉群的最终效果&#xff1a; 1、jenkins安装DingTalk插件&#xff0c;安装完成后重启 2、配置钉钉插件 参考官网文档&#xff1a;快速开始 | 钉钉机器人插件 系统管理 拉到最下面&#xff0c;可以看到钉钉配置 按照如下配置钉钉机器人 配置完成可以点击测试按钮&#xff0…...

从浏览器输入url到页面加载(六)前端必须了解的路由器和光纤小知识

前言 上一章我们说到了数据包在网线中的故事&#xff0c;说到了双绞线&#xff0c;还说到了麻花。这一章继续沿着这条线路往下走&#xff0c;说一些和cdn以及路由器相关&#xff0c;运营商以及光纤相关的小知识&#xff0c;前端同学应该了解一下的 目录 前言 1. CDN和路由器…...

C语言假期作业 DAY 06

题目 一、选择题 1、以下叙述中正确的是&#xff08; &#xff09; A: 只能在循环体内和 switch 语句体内使用 break 语句 B: 当 break 出现在循环体中的 switch 语句体内时&#xff0c;其作用是跳出该 switch 语句体&#xff0c;并中止循环体的执行 C: continue 语句的作用是&…...

[nlp] tokenizer加速:fast_tokenizer=True

fast_tokenizer 是一个布尔值参数,用于指定是否使用快速的 tokenizer。在某些情况下,使用快速的 tokenizer 可以加快模型训练和推理速度。如果 fast_tokenizer 参数为 True,则会使用快速的 tokenizer;否则,将使用默认的 tokenizer。 快速的 tokenizer 通常使用一些技巧来减…...

基于OpenCV solvePnP函数估计头部姿势

人脸识别 文章目录 人脸识别一、姿势估计概述1、概述2、姿态估计3、在数学上表示相机运动4、姿势估计需要什么5、姿势估计算法6、Levenberg-Marquardt 优化 二、solvePnP函数1、函数原型2、参数详解 三、OpenCV源码1、源码路径 四、效果图像示例参考链接 一、姿势估计概述 1、…...

STC12C5A系列单片机内部 EEPROM 的应用

参考范例程序。 eeprom.c #include "eeprom.h"/*---------------------------- Disable ISP/IAP/EEPROM function Make MCU in a safe state ----------------------------*/ void IapIdle() {IAP_CONTR 0; //Close IAP functionIAP_CMD 0; …...

搭建测试平台开发(一):Django基本配置与项目创建

一、安装Django最新版本 1 pip install django 二、创建Django项目 首先进入要存放项目的目录&#xff0c;再执行创建项目的命令 1 django-admin startproject testplatform 三、Django项目目录详解 1 testplatform 2 ├── testplatform  # 项目的容器 3 │ ├──…...

JavaWeb教程笔记

JavaWeb Java Web 1、基本概念 1.1、前言 web开发&#xff1a; web&#xff0c;网页的意思 &#xff0c; www.baidu.com静态web html&#xff0c;css提供给所有人看的数据始终不会发生变化&#xff01; 动态web 淘宝&#xff0c;几乎是所有的网站&#xff1b;提供给所有人…...

数据库压力测试方法小结

一、前言 在前面的压力测试过程中&#xff0c;主要关注的是对接口以及服务器硬件性能进行压力测试&#xff0c;评估请求接口和硬件性能对服务的影响。但是对于多数Web应用来说&#xff0c;整个系统的瓶颈在于数据库。 原因很简单&#xff1a;Web应用中的其他因素&#xff0c;…...

Spring Boot——Spring Boot自动配置原理

系列文章目录 Spring Boot启动原理 Spring Boot自动配置原理 系列文章目录前言一、Spring Boot自动配置原理剖析二、自动配置生效三、总结&#xff1a; 前言 一直在使用Spring Boot特别好奇的是为什么Spring Boot比Spring在项目构建和开发过程中要方便很多&#xff0c;无需编…...

深度学习:Pytorch最全面学习率调整策略lr_scheduler

深度学习&#xff1a;Pytorch最全面学习率调整策略lr_scheduler lr_scheduler.LambdaLRlr_scheduler.MultiplicativeLRlr_scheduler.StepLRlr_scheduler.MultiStepLRlr_scheduler.ConstantLRlr_scheduler.LinearLRlr_scheduler.ExponentialLRlr_scheduler.PolynomialLRlr_sched…...

【uniapp】更改富文本编辑器图片大小

代码块 //<view v-html"productDetails"></view><rich-text :nodes"productDetails"></rich-text>// 假设htmlContent字段是后台返回的富文本字段var htmlContent res.result.productDetailsconst regex new RegExp(<img, gi…...

数据结构和算法一(空间复杂度、时间复杂度等算法入门)

时间复杂度&#xff1a; 空间复杂度&#xff1a; 时间比空间重要 递归&#xff1a; 递归特征&#xff1a; 递归案例&#xff1a; 汉诺塔问题&#xff1a; def hanoi(n,A,B,C):if n>0:hanoi(n-1,A,C,B)print("moving from %s to %s"%(A,C))hanoi(n-1,B,A,C)hanoi…...

Pytorch深度学习-----神经网络的基本骨架-nn.Module的使用

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…...

QT开发快捷键

QT开发快捷键 alt enter // 自动创建类的定义 Ctrl / 注释当前行 或者选中的区域 Ctrl R 运行程序 Ctrl B Build 项目 CtrlShiftF 查找内容 F5 开始调试 ShiftF5 停止调试 F9 设置和取消断点 F10 单步前进 F11 单步进入函数 Shift F11 单步跳出函数 F1 // 查看帮助&#…...

RabbitMQ 教程 | RabbitMQ 入门

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…...

【雕爷学编程】MicroPython动手做(10)——零基础学MaixPy之神经网络KPU2

KPU的基础架构 让我们回顾下经典神经网络的基础运算操作&#xff1a; 卷积&#xff08;Convolution&#xff09;:1x1卷积&#xff0c;3x3卷积&#xff0c;5x5及更高的卷积 批归一化&#xff08;Batch Normalization&#xff09; 激活&#xff08;Activate&#xff09; 池化&…...

BUG分析以及BUG定位

一般来说bug大多数存在于3个模块&#xff1a; 1、前台界面&#xff0c;包括界面的显示&#xff0c;兼容性&#xff0c;数据提交的判断&#xff0c;页面的跳转等等&#xff0c;这些bug基本都是一眼可见的&#xff0c;不太需要定位&#xff0c;当然也不排除一些特殊情况&#xf…...

Day46 算法记录| 动态规划 13(子序列)

这里写目录标题 300.最长递增子序列 674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 视频解析&#xff1a; 第一层for循环遍历每一个元素&#xff0c; ------- 第二层for循环找到当前元素前面有几个小于该值的元素 结尾需要统计最多的个数 class Solution {pu…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...