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

【JavaEE】Spring(5):Mybatis(上)


一、什么是Mybatis

Mybatis是一个持久层的框架,它用来更简单的完成程序和数据库之间的交互,也就是更简单的操作和读取数据库中的数据

在讲解Mybatis之前,先要进行一些准备工作:

1. 为项目添加 Mybatis 相关依赖

2. 创建用户表以及对应的实体类

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (`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(),PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

实体类中的属性名要表中的字段名一一对应

@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;
}

3. 配置数据库连接

如果使⽤ MySQL 是 5.x 之前的使用的是"com.mysql.jdbc.Driver",如果是大于 5.x 使⽤的
是“com.mysql.cj.jdbc.Driver”
 

二、Mybatis基础操作

2.1打印日志

在Mybatis当中我们可以借助日志,查看到sql语句的执行、传递的参数以及执行结果,在配置⽂件中进行配置即可

mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #??sql??

2.2 参数传递

比如要查询id为3的用户信息,就需要在方法中添加一个参数,然后将这个参数告诉SQL语句,通过 #{} 的方式将参数传递给SQL

@Select("select username, `password`, age, gender, phone from userinfo where id= #{id} ")
UserInfo queryById(Integer id);

编写测试代码:

@Test
void queryById() {UserInfo userInfo = userInfoMapper.queryById(3);System.out.println(userInfo);
}

也可以使用@Param来给参数起别名,使用@Param后,#{}中的参数必须@Param中的参数相同

@Select("select username, `password`, age, gender, phone from userinfo where id= #{userid} ")
UserInfo queryById(@Param("userid")Integer id);

2.3 增(Insert)

Mapper接口:

@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo); //返回的是影响的行数

编写测试代码:

@Test
void insert() {UserInfo userInfo = new UserInfo();userInfo.setUsername("zhaoliu");userInfo.setPassword("zhaoliu");userInfo.setGender(2);userInfo.setAge(21);userInfo.setPhone("18612340005");userInfoMapper.insert(userInfo);
}

Updates:1就代表影响了一行数据,说明插入成功

如果对对象采用@Param,则 #{} 中需要使用参数.属性

@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{userinfo.username},#{userinfo.password},#{userinfo.age},# {userinfo.gender},#{userinfo.phone})")
Integer insert(@Param("userinfo") UserInfo userInfo);

返回主键

默认情况,插入方法返回的是影响行数,如果想要拿到自增id,可以在方法上方添加@Options注解

@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo); //返回的是影响的行数
  • useGeneratedKeys:这会令 MyBatis 使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键
  • keyProperty:指定能够唯⼀识别对象的属性,MyBatis会使用 getGeneratedKeys 的返回值或insert语句的selectKey子元素设置它的值
     

测试数据

@Test
void insert() {UserInfo userInfo = new UserInfo();userInfo.setUsername("sans");userInfo.setPassword("sans");userInfo.setGender(2);userInfo.setAge(21);userInfo.setPhone("18612340005");Integer count = userInfoMapper.insert(userInfo);System.out.println("添加数据条数:" +count +", 数据ID:" + userInfo.getId());
}

注意:设置 useGeneratedKeys = true 之后,⽅法返回值依然是受影响的行数,自增id会设置在上述 keyProperty 指定的属性中
 

2.4 删(Delete)

Mapper接口:

@Delete("delete from userinfo where id = #{id}")
Integer delete(Integer id);

测试代码:

@Test
void delete() {Integer row = userInfoMapper.delete(6);System.out.println(row);
}

2.5 改(Update)

Mapper接口:

@Update("update userinfo set username = #{username} where id = #{id}")
Integer update (String username, Integer id);

测试代码:

@Test
void update() {Integer row = userInfoMapper.update("sans", 5);System.out.println(row);
}

2.6 查(Select)

查询所有用户信息:

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
public List<UserInfo> queryAllUser();

测试代码:

@Test
void queryAllUser() {List<UserInfo> userInfoList = userInfoMapper.queryAllUser();System.out.println(userInfoList);
}

可以看到有部分值为null,这是因为在自动结果映射时,Mybatis会获取结果中返回的列名并在Java类中查找相同的属性名并赋值(忽略大小写)如果发现了表中的ID列和实体类中的id属性,此时Mybatis就会把ID列的值赋给id属性

这里我们的列和属性名分别如下:

由于无法正确结果映射,所以没有进行赋值

解决方法:

2.6.1 起别名

使用 as 给列名起别名,让列名和属性名相同

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, " +"create_time as createTime, update_time as updateTime from userinfo")
public List<UserInfo> queryAllUser();

此时再运行测试代码:

都已正确赋值

2.6.2 结果映射

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
@Results(id = "resultMap",value = {@Result(column = "delete_flag",property = "deleteFlag"),@Result(column = "create_time",property = "createTime"),@Result(column = "update_time",property = "updateTime")
})
List<UserInfo> queryAllUser();

通过id可以给@Results起别名,其他方法使用@ResultMap就可以复用该映射关系

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
@ResultMap("resultMap")
List<UserInfo> queryAllUser2();

2.6.3 开启驼峰命名

通过在配置文件中配置,将列名转换为驼峰命名,驼峰命名也是Java属性遵循的命名约定

mybatis:configuration:map-underscore-to-camel-case: true

Java代码不用做任何改变


🙉本篇文章到此结束

相关文章:

【JavaEE】Spring(5):Mybatis(上)

一、什么是Mybatis Mybatis是一个持久层的框架&#xff0c;它用来更简单的完成程序和数据库之间的交互&#xff0c;也就是更简单的操作和读取数据库中的数据 在讲解Mybatis之前&#xff0c;先要进行一些准备工作&#xff1a; 1. 为项目添加 Mybatis 相关依赖 2. 创建用户表以…...

记录 | MaxKB创建本地AI智能问答系统

目录 前言一、重建MaxKBStep1 复制路径Step2 删除MaxKBStep3 创建数据存储文件夹Step4 重建 二、创建知识库Step1 新建知识库Step2 下载测试所用的txtStep3 上传本地文档Step4 选择模型补充智谱的API Key如何获取 Step5 查看是否成功 三、创建应用Step1 新建应用Step2 配置AI助…...

【Spring】Spring启示录

目录 前言 一、示例程序 二、OCP开闭原则 三、依赖倒置原则DIP 四、控制反转IOC 总结 前言 在软件开发的世界里&#xff0c;随着项目的增长和需求的变化&#xff0c;如何保持代码的灵活性、可维护性和扩展性成为了每个开发者必须面对的问题。传统的面向过程或基于类的设计…...

八股——Java基础(四)

目录 一、泛型 1. Java中的泛型是什么 ? 2. 使用泛型的好处是什么? 3. Java泛型的原理是什么 ? 什么是类型擦除 ? 4.什么是泛型中的限定通配符和非限定通配符 ? 5. List和List 之间有什么区别 ? 6. 可以把List传递给一个接受List参数的方法吗&#xff1f; 7. Arra…...

游戏策划的分类

游戏策划是一个复杂而多面的领域&#xff0c;涉及游戏设计、玩法创新、故事叙述等多个方面。根据不同的职责和工作内容&#xff0c;游戏策划可以分为以下几类&#xff1a; 1. 系统策划 • 职责&#xff1a;负责游戏的整体系统设计&#xff0c;包括角色系统、技能系统、装备系统…...

面试场景问题集合

文章目录 项目地址一、1. 电商平台中订单未支付过期如何实现自动关单&#xff1f;2. 如果你的系统的 QPS 突然提升 10 倍你会怎么设计&#xff1f; 项目地址 教程作者&#xff1a;教程地址&#xff1a; 代码仓库地址&#xff1a; 所用到的框架和插件&#xff1a; dbt airflo…...

观察者模式 - 观察者模式的应用场景

引言 观察者模式&#xff08;Observer Pattern&#xff09;是设计模式中行为型模式的一种&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;使得当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会自动收到通知并更新。观察者模式广泛应用于事件处理系统…...

基于STM32的循迹小车设计与实现

1 系统方案设计 根据系统设计功能&#xff0c;展开基于STM32的循迹小车设计&#xff0c;整体设计框图如图2.1所示。系统采用STM32单片机作为控制器,通过L298驱动器控制两个直流电机实现对小车的运动控制&#xff0c;两路红外模块实现黑线的检测&#xff0c;HC-SR04超声波模块实…...

AI刷题-蛋糕工厂产能规划、优质章节的连续选择

挑两个简单的写写 目录 一、蛋糕工厂产能规划 问题描述 输入格式 输出格式 解题思路&#xff1a; 问题理解 数据结构选择 算法步骤 关键点 最终代码&#xff1a; 运行结果&#xff1a;​编辑 二、优质章节的连续选择 问题描述 输入格式 输出格式 解题思路&a…...

从理论到实践:Django 业务日志配置与优化指南

在现代 Web 开发中,日志记录是确保系统可维护性和可观测性的重要手段。通过合理的日志配置,我们可以快速定位问题、分析系统性能,并进行安全审计。本文将围绕 Django 框架,详细介绍如何配置和优化业务日志,确保开发环境和生产环境都能高效地记录和管理日志。 © ivwdc…...

达梦拷贝DM_HOME的复制安装

近期一个项目需求&#xff0c;需要在没有安装包的情况下&#xff0c;将达梦数据库安装到虚机上&#xff08;生产机上安装了达梦&#xff09;&#xff0c;故采用直接打包生产机DM_HOME的方式拷贝至虚机&#xff0c;再依次执行达梦的部分指令完成安装。以下为验证的步骤&#xff…...

网络工程师 (3)指令系统基础

一、寻址方式 &#xff08;一&#xff09;指令寻址 顺序寻址&#xff1a;通过程序计数器&#xff08;PC&#xff09;加1&#xff0c;自动形成下一条指令的地址。这是计算机中最基本、最常用的寻址方式。 跳跃寻址&#xff1a;通过转移类指令直接或间接给出下一条指令的地址。跳…...

vue3和vue2的区别有哪些差异点

Vue3 vs Vue2 主要差异对比指南 官网 1. 核心架构差异 1.1 响应式系统 Vue2&#xff1a;使用 Object.defineProperty 实现响应式 // Vue2 响应式实现 Object.defineProperty(obj, key, {get() {// 依赖收集return value},set(newValue) {// 触发更新value newValue} })Vue3…...

第一届“启航杯”网络安全挑战赛WP

misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…...

DeepSeek R1与OpenAI o1深度对比

文章目录 引言技术原理DeepSeek R1OpenAI o1 性能表现官方数据推理任务知识密集型任务通用能力 价格对比应用场景科研与技术开发自然语言处理&#xff08;NLP&#xff09;企业智能化升级教育与培训数据分析与智能决策 部署与集成DeepSeek R1OpenAI o1 伦理考量DeepSeek R1OpenA…...

图漾Halcon版本SDK使用教程【V1.1.0新版本】

1.下载并安装 Halcon 1.1 下载Halcon软件 在 Halcon 官网(https://www.mvtec.com/downloads) 下载 Halcon (Windows 版) 安装包&#xff0c;并根据官方文档安装 Halcon&#xff0c;下载HALCON24.11Progress-Steady。 1.2 安装Halcon 1.解压HALCON 24.11.1.0的安装包压缩文件…...

基于区块链的数字身份认证:安全与隐私的未来

友友们好! 我的新专栏《Python进阶》正式启动啦!这是一个专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会找到: ● 深入解析:每一篇文章都将…...

软件开发中的密码学(国密算法)

1.软件行业中的加解密 在软件行业中&#xff0c;加解密技术广泛应用于数据保护、通信安全、身份验证等多个领域。加密&#xff08;Encryption&#xff09;是将明文数据转换为密文的过程&#xff0c;而解密&#xff08;Decryption&#xff09;则是将密文恢复为明文的过程。以下…...

计算树的叶子节点,使用c语言实现

//树的数据结构 typedef struct node{ ElemType data; /*数据域*/ struct node *child, *brother; /*孩子与兄弟域 */ }Tree; //计算树的叶子节点的个数 int Leaves (Tree *root){/*计算以孩子-兄弟表示法存储的森林的叶子数*/ if(root) if(root-&…...

20.Word:小谢-病毒知识的科普文章❗【38】

目录 题目​ NO1.2.3文档格式 NO4.5 NO6.7目录/图表目录/书目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完&#xff0c;确定之后记得保存最后所有操作完记得再次删除空行 题目 NO1.2.3文档格式 样式的应用 选中应用段落段落→开始→选择→→检查→应用一个一个应用ctr…...

滑动窗口详解:解决无重复字符的最长子串问题

滑动窗口详解&#xff1a;解决无重复字符的最长子串问题 在算法面试中&#xff0c;“无重复字符的最长子串”问题是一个经典题目&#xff0c;不仅考察基础数据结构的运用&#xff0c;还能够反映你的逻辑思维能力。而在解决这个问题时&#xff0c;滑动窗口&#xff08;Sliding …...

力扣-链表-19 删除链表倒数第N个节点

思路 链表题目中操作链表的需要找到要操作节点的上一个节点&#xff0c;所以cur是当前想要操作的节点上一个节点 代码 class Solution { public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummy_head new ListNode();dummy_head->next head;int s…...

算法题(49):反转链表II

审题&#xff1a; 需要我们对指定范围的链表进行反转&#xff0c;并返回反转后链表的头结点 思路&#xff1a; 方法一&#xff1a;vector法 我们先遍历一次链表&#xff0c;并把数据对应的存在数组中&#xff0c;然后利用数组的reverse方法进行反转数据&#xff0c;最后再遍历一…...

基于SpringBoot多数据源解决方案

最近在学习SpringBoot的时候&#xff0c;需要同时用两个不同的数据库连接服务&#xff0c;在网上学习了之后&#xff0c;下文以连接一个MySQL数据库和一个SqlServer数据库为例。 配置数据源连接信息 在配置文件中&#xff0c;配置对应的数据库连接信息&#xff0c;相比于单数…...

通过案例研究二项分布和泊松分布之间关系(2)

通过案例研究二项分布和泊松分布之间关系 2. 汽车出事故的概率p与保险公司盈利W之间的关系3.通过遗传算法多次迭代计算控制p为多少时公司盈利最大(1) 计算过程(2) 结果及分析(计算过程详见附录二程序) 4.改变思路求解固定p为0.01时,保险费用如何设置公司可获得最大利润(1)计算过…...

RISC-V读书笔记4

目录 乘法与除法 RV32F 和 RV32D&#xff1a;单精度和双精度浮点数 原子操作 压缩指令 向量 乘法与除法 RV32M属于扩展的指令&#xff0c;主要扩展的就是便捷的乘法和除法指令。 除法&#xff1a; 商 (被除数− 余数) 除数 被除数 除数 商 余数 余数 被除数− (商 …...

【Uniapp-Vue3】request各种不同类型的参数详解

一、参数携带 我们调用该接口的时候需要传入type参数。 第一种 路径名称?参数名1参数值1&参数名2参数值2 第二种 uni.request({ url:"请求路径", data:{ 参数名:参数值 } }) 二、请求方式 常用的有get&#xff0c;post和put 三种&#xff0c;默认是get请求。…...

大数据学习之SCALA分布式语言三

7.集合类 111.可变set一 112.可变set二 113.不可变MAP集合一 114.不可变MAP集合二 115.不可变MAP集合三 116.可变map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前导入如下包 import scala . collection . mutable // 可变 Map 集合 object Ma…...

深度解析:MyBatis-Plus实现分页查询的封装!

全文目录&#xff1a; 开篇语前言摘要概述什么是分页查询&#xff1f;为什么选择 MyBatis-Plus&#xff1f;本文目标 源码解析分页插件核心逻辑 使用案例分享1. 配置 MyBatis-Plus 分页插件2. 定义分页查询方法3. Controller 层调用 应用场景案例优缺点分析优点缺点 核心类方法…...

第05章 14 绘制人脸部的PolyData并使用小圆锥体来展现法线

在VTK中&#xff0c;绘制人脸部的PolyData并使用小圆锥体来展现法线是一个常见的任务。这个过程可以通过以下步骤实现&#xff1a; 读取人脸部的PolyData&#xff1a;可以使用VTK的读取模块读取一个包含人脸部的.vtk或.obj文件。计算法线&#xff1a;使用VTK的vtkPolyDataNorm…...