MyBatis - 单元测试 参数传递 注解 CRUD

目录

1. MyBatis 简介

2. 简单使用 MyBatis

2.1 创建 MyBatis 项目

2.2 连接数据库

2.3 创建 Java 类

2.4 创建 Mapper 接口

 2.5 在测试类中执行

3. 单元测试

3.1 @Test

3.2 @SpringBootTest

3.3 @BeforeEach / @AfterEach

4. MyBatis 基础操作

4.1 配置 MyBatis 打印日志

4.2 参数传递

4.2.1 传递单个参数

4.2.2 传递多个参数

4.2.2.1 @Param: 参数绑定/重命名

4.2.2 接收结果

5. 新增数据(@Insert)

5.1 @Insert

5.2 @Options: 返回主键

6. 查询数据(@Select)

6.1 解决映射问题

6.1.1 表中字段起别名

​编辑6.1.2 @Results 结果映射

6.1.3 配置驼峰自动转换 (推荐)

7. 更新数据(@Update)

8. 删除数据(@Delete)


1. MyBatis 简介

我们之前提到过应用分层:

  1. Controller => 控制/表现层, 用于和用户交互(接收参数, 返回结果)
  2. Service => 业务逻辑层, 处理业务数据
  3. Dao => 数据层, 对数据进行管理和查询

MyBatis 就是一款优秀的 Dao 层框架.

我们之前学习过 jdbc 操作数据库, 操作繁琐麻烦, 并且每次操作都需要写很多重复的代码, 如: 创建 DataSource, 获取连接, 释放资源, ....

MyBatis 就是基于 jdbc 封装而成的框架, 就类似于 Spring 是基于 serverLet 封装的一样.

也就是说, MyBatis 是一款操作数据库的框架, 它极大的简化了操作数据库的流程, 能够让我们写更少的代码, 更容易的操作数据库.

注意: MyBatis 底层仍然使用 jdbc 来操作数据库, 但我们不再使用 jdbc, 只需操作 MyBatis, 让 MyBatis 操作 jdbc 即可.

2. 简单使用 MyBatis

首先, 我们先使用 sql 创建 mybatis_test 数据库, 再创建 user_info 表, 在表中插入数据.

数据插入成功后, 如下图所示:

接着, 我们就可以使用 MyBatis 操作 mybatis_test 数据库了.

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;

CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
USE mybatis_test;

-- 创建表[用户表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (
        `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
        `username` VARCHAR ( 127 ) NOT NULL,
        `password` VARCHAR ( 127 ) NOT NULL,
        `age` TINYINT ( 4 ) NOT NULL,
        `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
        `phone` VARCHAR ( 15 ) DEFAULT NULL,
        `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now() ON UPDATE now(),
        PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 

-- 添加用户信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );


-- 创建文章表
DROP TABLE IF EXISTS article_info;
        
CREATE TABLE article_info (
        id INT PRIMARY KEY auto_increment,
        title VARCHAR ( 100 ) NOT NULL,
        content TEXT NOT NULL,
        uid INT NOT NULL,
        delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
        create_time DATETIME DEFAULT now(),
        update_time DATETIME DEFAULT now() 
) DEFAULT charset 'utf8mb4';

-- 插入测试数据
INSERT INTO article_info ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );

2.1 创建 MyBatis 项目

使用 MyBatis, 依旧创建 SpringBoot 项目即可.

要进行说明的是, Spring 和 MyBatis 是 "两家人", 是两个不同的框架, 但是由于 MyBatis 功能强大, 于是 Spring 集成了 MyBatis, 就像 12306 集成了美团的外卖服务和其他公司的保险服务一样.

接下来, 我们创建 SpringBoot 项目, 并通过插件导入 MyBatis 依赖:

2.2 连接数据库

首先, 需要进行数据库连接的配置(yml 格式为例):

# 数据库配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 111111
    driver-class-name: com.mysql.cj.jdbc.Driver

以上配置数据的主要功能为: 将 Java 进程连接到本地运行的名为 mybatis_test 的 MySQL 数据库, 用户名为 root, 密码为 111111.
(注意: 避免出错, 不要手写!! 直接复制到配置文件中)

2.3 创建 Java 类

这里, 我们使用 MyBatis 执行最简单的 select 语句.

MyBatis 会将查询结果绑定到 Java 对象的属性中, 这里我们使用 UserInfo 对象接收.

import lombok.Data;
import java.util.Date;

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2.4 创建 Mapper 接口

对接口使用 @Mapper 注解, 告诉 MyBatis 这是一个 Mapper 接口, 并让 Spring 管理该接口的实现类.

在 Mapper 接口中, 会定义数据库操作的方法, 例如: 在 selectAll 方法的 @Select 注解中指定要执行的 SQL.

综上:

  • @Mapper: 将接口的实现类的对象交给 Spring 管理
  • @Select: 定义 SQL 语句, 当调用该方法时会执行其中的 SQL 语句
@Mapper
public interface UserInfoMapper {
    @Select("select * from user_info")
    List<UserInfo> selectAll();
}

 2.5 在测试类中执行

最后, 在测试类中进行测试, 观察 MyBatis 执行结果.

@SpringBootTest: 为该测试类提供 Spring 运行环境

@Autowired 获取实现类 Bean 后, 实现类 Bean 调用 SelectAll 方法, MyBatis 执行该方法 @Select 注解中的 SQL, 并将查询得到的结果集的每一行映射到每一个 UserInfo 对象的属性中, 并将每一个 UserInfo 对象放入 List 中.

3. 单元测试

在之前的学习中, 我们想要测试所写代码是否正确, 我们通常都会在 main 方法中通过打印来进行测试. 其实, 正确的做法应该是在测试类中进行测试, 这样可以将项目代码和测试代码分离开来, 一目了然的区分项目代码和测试代码.

这里所说的测试代码不是测试人员进行测试所写的代码, 而是我们开发人员进行单元测试时写的带代码, 毕竟项目的第一个测试人员, 一定是开发者自己.

其实, 在上文简单使用 MyBatis 时, 就已经用到了测试类, 接下来, 为大家详细讲一讲.

3.1 @Test

在测试类中, 使用 @Test 注解标记方法, 该方法可以直接运行, 不需要通过调用就可以直接执行:

3.2 @SpringBootTest

@SpringBootTest 的作用是: 为测试类加载 Spring 运行环境, 它会启动一个完整的 Spring 应用上下文, 也就是说我们可以在测试类中使用 Spring 的所有特性.

当我们需要在测试类中使用到 Spring 的相关功能时(如: @Autowired 依赖注入), 就需要给类加上 @SpringBootTest. (如果不需要使用 Spring 的功能, 就可以不加, 如上文 @Test 所示举例)

3.3 @BeforeEach / @AfterEach

@BeforeEach: 在每一个测试方法执行前, 执行的方法

@AfterEach: 在每一个测试方法执行后, 执行的方法

 

4. MyBatis 基础操作

4.1 配置 MyBatis 打印日志

配置 MyBatis 打印日志后, 我们可以借助日志查看注解的 SQL 语句, 参数的传递以及 SQL 的执行结果. 

# 配置打印 MyBatis⽇志
mybatis:
  configuration: 
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4.2 参数传递

上文, 我们演示了如何使用 @Select 查询标准所有的记录, 但是在绝大多数的查询时, 我们都是会加上 where 来锁定我们要查询的目标的.

此时, 我们就需要将参数传递到 SQL 语句中, 以到达我们查询的目的.

4.2.1 传递单个参数

在 MyBatis 中, 使用 #{参数名称} 的形式来进行参数的传递.

注意: 此时只传递了一个参数, 因此 #{} 中的名称可以任意命名, 无论是什么名称都会绑定成功:

4.2.2 传递多个参数

同样使用 #{参数名称} 的形式来传递参数:

注意: 此时, 传递的参数有多个, MyBatis 会根据 #{} 中参数的名称来匹配方法中的形参.

和参数顺序无关, 即使调换形参的顺序, MyBatis 也会根据参数名称进行匹配:

但是, 由于此时传递的是多个参数, 因此 #{} 中的参数不可随意命名, 名称必须和方法形参的名称相匹配, 否则匹配失败报错:

如上图, #{} 中除了使用形参名称和形参进行匹配外, 还可以根据形参顺序使用 param1, param2, ... 进行匹配, 但不建议, 因为可读性差.

4.2.2.1 @Param: 参数绑定/重命名

上文说到, 传递多个参数时, #{} 中的参数名称必须和方法形参的名称相匹配. 

#{} 中的名称除了和形参名称相同能够匹配成功外, 还可以使用 @Param 自定义参数名(对方法形参使用), 进行参数绑定.

综上, 方法形参和参数占位符(#{})能够匹配成功的方式有两种:

  1. 两者参数使用相同的名称
  2. 使用 @Param 进行参数绑定

4.2.2 接收结果

这里以 select 操作为例:

  1. 当查询返回的结果集只有 0 条或 1 条记录时, 使用对象或者集合接收均可.
  2. 当查询返回的结果集有多条记录时, 必须使用集合接收.

5. 新增数据(@Insert)

5.1 @Insert

使用 MyBatis 进行数据插入时, 需要使用 @Insert 注解.

由于插入数据时, 需要给表中的多个字段赋值, 为了简化代码, 我们可以直接给方法传一个对象(传单个参数也是可以的), MyBatis 会根据对象中属性的名称, 自动匹配到对应的参数占位符(#{})上.

此外, 上一篇博客说到, 可以使用 @Param 进行参数绑定, 那么我们对对象使用 @Param 观察结果: 

我们发现, 对象使用 @Param 进行参数绑定后, 程序就会出错.

我们需要这样进行修改:

5.2 @Options: 返回主键

通过 @Insert 插入数据后, 还可以通过 @Options 获取新增数据的主键值(ID).

6. 查询数据(@Select)

在上文中, 已经讲解了 MyBatis 进行数据查询的大部分内容, 但是遗留了一个问题:

当我们打印 @Select 的查询结果时, 有些属性的值为 null:

原因其实很简单: 由于数据库表中字段的名称和 Java 类中属性的名称不相同, 导致值没有映射成功:

6.1 解决映射问题

解决办法有三种:

  1. 查询时, 给表中字段起别名, 使表中字段和 Java 属性名称相同
  2. 使用 @Results
  3. 修改配置, 使小驼峰和蛇形名称相绑定

6.1.1 表中字段起别名

查询时, 给表中字段起别名, 使得查询结果集中的字段名称和 Java 属性名称相同:

这样, 就能够映射成功了:

6.1.2 @Results 结果映射

虽然给字段起别名的方式能够映射成功, 但是这种方式太麻烦了. 有一种比较简洁的方式: 使用 @Results 注解.

@Results 中的 value 属性是 @Result[] 类型的 , @Result 便可以设置数据库字段和 Java 属性之间的映射关系. 由于 value 是 @Result[] 类型即数组的类型的, 因此可以设置多组的映射关系:

6.1.3 配置驼峰自动转换 (推荐)

虽然 @Results 的方式已经够简单了, 但是, 还有更加 "懒汉" 的方式 --- 

其实, Java 属性和 数据库字段映射不上的根本原因就是: 两者命名规范不同.

Java 属性使用小驼峰命名, 数据库字段使用蛇形命名(_), 但两者参数名称都是很相似的, 因此, 我们只需在配置文件中, 将小驼峰的格式和蛇形格式绑定到一起即可:

# 配置驼峰⾃动转换
mybatis:
  configuration:
    map-underscore-to-camel-case: true 

这样, 我们不需使用任何注解, 就能够将数据库中的蛇形字段和 Java 中的小驼峰属性绑定到一起了:

因此, 在对 Java 属性进行命名时, 如果可以和数据库字段名称完全一致则完全一致, 如果由于命名规范的限制而无法完全一致, 则 Java 属性名称应使用数据库字段名称相同单词的小驼峰形式, 以便通过配置文件能够成功映射.

7. 更新数据(@Update)

使用 MyBatis 进行 update 操作, 需要使用 @Update 注解. 

同样, 进行数据更新时, 既可以传入单个单个的参数, 也可以直接传入一个对象, MyBatis 会根据对象属性的名称, 匹配到对应的 #{} 中.

同样, 如果对象使用了 @Param 进行参数绑定, 那么 #{} 中的参数名称要使用 对象名.属性名:

8. 删除数据(@Delete)

使用 MyBatis 删除记录, 使用 @Delete 注解. 

 


END 

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

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

相关文章

课程2. 机器学习方法论

课程2. 机器学习方法论 训练算法并评估其质量将样本分成训练和测试。分层 交叉验证方法sklearn 接口算法模型训练模型的应用质量评估 数据预处理标准缩放Violinplot 数据集使用模型Pipeline 在上一讲中&#xff0c;我们讨论了机器学习专家面临的挑战。无论解决的问题类型和解决…

CentOS 7使用RPM安装MySQL

MySQL是一个开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;允许用户高效地存储、管理和检索数据。它被广泛用于各种应用&#xff0c;从小型的web应用到大型企业解决方案。 MySQL提供了丰富的功能&#xff0c;包括支持多个存储引擎、事务能力、数据完整…

涂层,如同一道守护之光,有效遏制了QD(量子点)那如星辰般忽明忽暗的闪烁与如垂暮手电筒般黯淡无光的褪色现象。

涂层&#xff0c;如同一道守护之光&#xff0c;有效遏制了QD&#xff08;量子点&#xff09;那如星辰般忽明忽暗的闪烁与如垂暮手电筒般黯淡无光的褪色现象。俄克拉荷马大学&#xff08;University of Oklahoma&#xff09;的一项卓越研究&#xff0c;犹如破晓之光&#xff0c;…

C++第六节:stack和queue

本节目标&#xff1a; stack的介绍与使用queue的介绍与使用priority_queue的介绍与使用容器适配器模拟实现与结语 1 stack&#xff08;堆&#xff09;的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;只能从容器的一端进行元素的插…

五分钟快速学习优秀网站的HTML骨架布局设计

一.编写多级过滤脚本&#xff0c;在控制台执行copy方法进行提取&#xff1a; 过滤脚本脚本 // 在浏览器F12的控制台里&#xff0c;直接执行以下脚本 copy(document.documentElement.outerHTML// 一级过滤&#xff1a;移除动态内容.replace(/<script\b[^>]*>[\s\S]*?…

硬件学习笔记--47 LDO相关基础知识介绍

目录 1.LDO主要功能介绍 2.LDO相关参数介绍 3.使用方法 4.优、缺点 1.LDO主要功能介绍 LDO&#xff08;Low Dropout Regulator&#xff09;是一种线性稳压器&#xff0c;用于将输入电压转换为稳定的输出电压。其主要功能包括&#xff1a; 1&#xff09;稳压功能&#xff1…

利用矩阵相乘手动实现卷积操作

卷积&#xff08;Convolution&#xff09; 是信号处理和图像处理中的一种重要操作&#xff0c;广泛应用于深度学习&#xff08;尤其是卷积神经网络&#xff0c;CNN&#xff09;中。它的核心思想是通过一个卷积核&#xff08;Kernel&#xff09; 或 滤波器&#xff08;Filter&am…

STM32-HAL库初始化时钟

使能和失能外设GPIOA 时钟信号初始化函数 HAL_RCC_OscConfig函数&#xff1a; HAL_StatusTypeDef是该函数的返回值类型,最顶上的那句话只是这个函数的原型 HAL_RCC_ClockConfig函数&#xff1a; 因为FLASH实际上只能支持24MHz的时钟信号所以如果用高于24MHz的信号输入则要用到等…

windows环境执行composer install出错

现在的项目环境都是要求比较新的版本&#xff0c;就比如今天部署测试一个新框架遇到了下面这些问题&#xff0c;报错原因有以下几点&#xff1a; PHP版本低了&#xff0c;现在的新项目都是要求PHP8以上版本&#xff1b;指令废弃&#xff0c;配置文件禁用即可&#xff1b;切换P…

Three.js 入门(光线投射实现3d场景交互事件)

本篇主要学习内容 : 光线投射器交互事件 点赞 关注 收藏 学会了 1.光线投射器 Raycaster 此类旨在协助光线投射。光线投射用于鼠标拾取&#xff08;确定鼠标在 3D 空间中的哪些对象上&#xff09;等。 Raycaster( origin : Vector3, direction : Vector3, near : Float,…

蓝桥杯web第三天

展开扇子题目&#xff0c; #box:hover #item1 { transform:rotate(-60deg); } 当悬浮在父盒子&#xff0c;子元素旋转 webkit display: -webkit-box&#xff1a;将元素设置为弹性伸缩盒子模型。-webkit-box-orient: vertical&#xff1a;设置伸缩盒子的子元素排列方…

Unity 使用NGUI制作无限滑动列表

原理&#xff1a; 复用几个子物体&#xff0c;通过子物体的循环移动实现&#xff0c;如下图 在第一个子物体滑动到超出一定数值时&#xff0c;使其放到最下方 --------------------------------------------------------------》 然后不停的循环往复&#xff0c;向下滑动也是这…

网络安全蜜罐产品研究现状

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、知识点总结 1、蜜罐&#xff08;Honeypot&#xff09;&#xff1a;诱捕攻击者的一个陷阱。 2、蜜网&#xff08;Honeynet&#xff09;&#xff1a;采用了技术…

SpringBoot3—场景整合:环境准备

一、云服务器 阿里云服务器开通安装以下组件 dockerrediskafkaprometheusgrafana 下载windterm&#xff1a;https://github.com/kingToolbox/WindTerm/releases/download/2.5.0/WindTerm_2.5.0_Windows_Portable_x86_64.zip 重要&#xff1a;开通云服务器以后&#xff0c;请一…

Ollama进行DeepSeek本地部署存在安全风险解决方案,nginx反向代理配置

文章目录 概要整体架构流程技术细节**## 1.下载nginx [https://nginx.org/en/download.html](https://nginx.org/en/download.html),推荐Stable version稳定版**2.下载完成解压文件,打开conf文件夹下的nginx.conf,贴上反向代理配置3.然后点击解压文件夹下的nginx.exe,启动成…

【音视频】ffmpeg音视频处理基本流程

一、ffmpeg音视频处理基本流程 首先先看两条命令 ffmpeg -i 1.mp4 -acodec copy -vcodec libx264 -s 1280x720 2.flv ffmpeg -i 1.mp4 -acodec copy -vcodec libx265 -s 1280x720 3.mkv-i :表示输入源&#xff0c;这里是1.mp4&#xff0c;是当前路径下的视频文件-acodec copy…

计算机网络基础:认识网络拓扑结构

计算机网络基础&#xff1a;认识网络拓扑结构 一、前言二、网络拓扑结构的基本概念2.1 定义2.2 作用 三、常见的物理拓扑结构3.1 总线型拓扑结构3.1.1 定义和结构3.1.2 工作原理3.1.3 优点3.1.4 缺点3.1.5 适用场景3.1.6 示例图 3.2 星型拓扑结构3.2.1 定义和结构3.2.2 工作原理…

基于Android平台的SOME/IP测试模块 EPT-ETS

在汽车产业智能化、网联化的时代浪潮中&#xff0c;汽车电子系统正经历着前所未有的变革。SOME/IP&#xff08;Scalable service-Oriented MiddlewarE over IP&#xff09;协议作为汽车电子通信领域的关键技术&#xff0c;其稳定性、可靠性与高效性对于整车性能的提升起着至关重…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-2.2.3案例:电商订单日志每秒10万条写入优化

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 Elasticsearch批量写入性能调优实战&#xff1a;2.2.3 案例&#xff1a;电商订单日志每秒10万条写入优化1. 原始架构与瓶颈分析1.1 初始集群配置1.2 性能瓶颈定位 2. 全链路…

解决redis lettuce连接池经常出现连接拒绝(Connection refused)问题

一.软件环境 windows10、11系统、springboot2.x、redis 6 7 linux&#xff08;centos&#xff09;系统没有出现这问题&#xff0c;如果你是linux系统碰到的&#xff0c;本文也有一定大参考价值。 根本思路就是&#xff1a;tcp/ip连接的保活(keepalive)。 二.问题描述 在spr…