MyBatis操作数据库实现
说明:MyBatis是作用于三层架构开发,数据访问层(Data Access Object)的框架,用于访问数据库,对数据进行操作。
一、环境搭建
首先,创建一个SpringBoot模块,然后把MyBatis的环境搭建起来。因为MyBatis是作用于Dao层的,故先省去Service层,重点关注Dao层中与数据库的交流。
(1)创建Springboot模块
我这里是手动创建SpringBoot模块方式,在idea中创建一个SpringBoot模块,参考(http://t.csdn.cn/RJ2gu)
pom.xml文件中添加的继承和依赖

(2)添加MyBatis依赖
在SpringBoot模块基础上,添加MyBatis依赖和数据库的配置文件
添加MyBatis依赖

添加数据库的配置文件(application.properties)
放在 src/main/resources 目录下,注意 数据库链接(数据库端口号、数据库名)、用户名和密码

(3)添加其他依赖
启动项目,我们还需要一些额外的依赖(lombok、druid、test),方便开发和测试,另外数据库的配置文件也添加一些额外配置
pom.xml文件
lomhok:可以帮助我们一键生成javaBean的set()、get()、toString()方法;
druid:使用阿里巴巴提供的连接池;
test:方便测试功能;

数据库的配置文件(application.properties)
开启驼峰支持:Java和MySQL的命名规范不同,如createTime对应的是MySQL中的create_time,开启此设置,可以自动匹配;
SQL日志:可以将执行的SQL语句打印在控制台中,方便我们排查SQL语句是否执行错误;

(4)准备数据库
创建数据库,注意数据库名和上面application.properties中配置的数据库名要一致
创建表,添加一些数据
create database mybatis;use mybatis;create table tb_stu(id int auto_increment primary key comment '序列号',name varchar(10) comment '姓名',gender varchar(2) comment '性别',age tinyint comment '年龄',create_time date comment '创建日期'
) comment '学生表';insert into tb_stu values (null, '加缪', '男', 20, null),(null, '萨特', '男', 25, null),(null, '陀思妥耶夫斯基', '男', 30, '2023-06-08'),(null, '阿加莎克里斯蒂','女','27', null);
(5)创建类
创建学生类(Student)
@Data、@NoArgsConstructor、@AllArgsConstructor,相当于自动为类添加了set()、get()、toString()、无参和全参构造方法
package com.essay.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDate;/*** 学生类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {private Integer id;private String name;private String gender;private Integer age;private LocalDate createTime;
}
创建Mapper类
Mapper,是Dao层中,MyBatis的取名方式,也是Dao层的具体表现之一。
package com.essay.mapper;import org.apache.ibatis.annotations.Mapper;@Mapper
public interface StuMapper {/*** 访问数据库,处理数据*/}
创建启动类(Start)
package com.essay;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Start {public static void main(String[] args) {SpringApplication.run(Start.class, args);}
}
创建测试类(MyTest),模拟Controller层。本来应该注入Service层依赖,因为是介绍MyBatis,我这里直接注入Mapper(Dao层)依赖
package com.essay;import com.essay.mapper.StuMapper;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MyTest {// 注入Mapper依赖@Autowiredprivate StuMapper stuMapper;// 接收前端请求,响应数据
}
另外,还需要注意两点:
a. 测试类的目录要与main中的启动类平行

b. 测试类的类名,不要取名为Test,因为测试的注解也是Test(@Test)
至此,环境搭建完成,可以开始紧张又刺激的开发了。
二、注解方式
注解方式,是将对数据库进行操作的SQL语句,写在Dao层的各个方法上。
(1)查找所有:
在MyTest(Controller层)中接收请求
@SpringBootTest
public class MyTest {// 注入Mapper依赖@Autowiredprivate StuMapper stuMapper;/*** 查找所有*/@Testpublic void findAll(){List<Student> list = stuMapper.findAll();System.out.println(list);}
}
在StuMapper(Dao层)中访问数据库,返回数据
@Mapper
public interface StuMapper {/*** 查找所有*/@Select("select * from tb_stu")List<Student> findAll();
}

(2)添加数据:
在MyTest(Controller层)中接收请求
这里是我手动创建的对象,在正式业务中,数据会由前端传过来,封装成一个对象(需要使用@RequestParam注解),另外对象的创建时间会在Service层中设置,之后再传至Dao层写入数据库。
/*** 添加记录*/@Testpublic void insertStu(){Student s = new Student();s.setName("伏尔泰");s.setGender("男");s.setAge(40);s.setCreateTime(LocalDate.now());stuMapper.insertStu(s);}
在StuMapper(Dao层)中访问数据库,添加数据
#{},表示对象s中的对应的属性值,所以一定要注意,#{}里面的名称是对象里面的属性名,而不是数据库里面的字段名
/*** 添加记录*/@Insert("insert into tb_stu(name,gender,age,create_time) value(#{name},#{gender},#{age},#{createTime})")void insertStu(Student s);

(3)修改数据:
在MyTest(Controller层)中接收请求,同样,具体业务中,被修改的对象会被前端传过来,我这里是手动创建模拟修改
/*** 根据ID修改记录*/@Testpublic void updateStu(){Student s = new Student();s.setId(1);s.setName("加缪——修改后");stuMapper.updateStu(s);}
在StuMapper(Dao层)中访问数据库,修改数据
/*** 修改记录*/@Update("update tb_stu set name=#{name},gender=#{gender},age=#{age} where id=#{id}")void updateStu(Student s);
这里,问题出现了,除了name,其他字段也被修改成了。这是因为传进来的对象,仅设置了name,其他属性未设置默认是null。那有没有一种方案,修改时判断对象的属性值是否为空,不为空说明需要修改此字段,则修改数据库中的数据;为空说明不需要修改此字段,那么数据库中就不修改,在xml方式中可以解决此问题(在修改之前,根据ID把数据库中的对象值先找出来,然后在Service层做逻辑判断,是否也可以解决?)。

(4)删除数据:
在MyTest(Controller层)中接收请求,我这里模拟删除ID是为1的记录
/*** 根据ID删除记录*/@Testpublic void deleteStu(){Integer id = 1;stuMapper.delete(id);}
在StuMapper(Dao层)中访问数据库,删除数据
/*** 根据ID删除记录*/@Delete("delete from tb_stu where id=#{id}")void delete(Integer id);


小结
以上展现了使用注解方式,对数据库进行查找所有、添加数据、根据ID修改和删除操作,如果还需要做条件查找、删除所有记录等功能,可以先写好SQL语句,根据SQL语句所需要的参数,再设计好Controller层的代码。
三、xml方式
除了注解方式,MyBatis还提供了xml的方式,将方法对应的SQL语句配置到xml文件中,通过方法调用,实现对数据操作。首先,创建好Mapper类对应的xml文件。
创建xml文件
创建xml文件,需要注意以下两点:
a. xml文件需要和Mapper类平行同包同名

b. 在Resource文件夹中创建多级目录,不能使用点(.),要用斜杠(/)


以上两点至关重要,这是xml文件与Mapper类建立联系的过程,联系建立不起来,程序跑不起来。
文件创建好之后,首先在xml文件开头添加约束,不要手敲,建议从官网复制过来(https://mybatis.net.cn/getting-started.html)

约束添加后,敲一个mapper标签,属性namaspace为Mapper类的全类名。同样,也不要手敲,点击类文件,快捷键ctrl+alt+shift+c,复制粘贴过来。

(1)查找所有:
在xml文件中配置查找所有方法
StuMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.essay.mapper.StuMapper"><!--1.查找所有--><select id="findAll" resultType="com.essay.domain.Student">select * from tb_stu;</select></mapper>
StuMapper类(前面写的注解删掉)
/*** 查找所有*/List<Student> findAll();
需要注意以下两点:
a. xml文件中标签id要与StuMapper类中的对应的方法名一致;
b. resultType为返回类型,即返回的数据,需要封装为对象的对象的类全名。

(2)添加数据:
在xml文件中配置添加数据方法
<!--2.添加数据--><insert id="insertStu">insert into tb_stu(name,gender,age,create_time) value(#{name},#{gender},#{age},#{createTime})</insert>
StuMapper类(前面写的注解删掉)
/*** 添加记录*/void insertStu(Student s);
MyTest(测试类)
/*** 添加记录*/@Testpublic void insertStu(){Student s = new Student();s.setName("卢梭");s.setGender("男");s.setAge(20);s.setCreateTime(LocalDate.now());stuMapper.insertStu(s);}

(3)修改数据:
前文说过使用注解方式修改数据的问题,修改指定字段的数据,因为传入Dao层的是一个新建的javaBean对象,未设置的属性,是null,修改数据库时会覆盖原数据。导致欲修改的字段,修改成功;未设置的字段,因为修改被置空。
使用xml方式,可以解决这个问题。使用if标签,判断传入的属性值是否为空,不为空说明是前端请求需要修改的字段,就修改;为空,说明是前端不需要修改的字段,就不修改。
StuMapper.xml文件(注意不要漏掉最后的where语句)
<!--3.修改数据--><update id="updateStu">update tb_stu<set><if test="name!=null and name!='' ">name=#{name},</if><if test="gender!=null and gender!='' ">gender=#{gender},</if>/*因为age是Integer类型,仅判断不为null就行,下面的时间格式也是*/<if test="age!=null" >age=#{age},</if><if test="createTime!=null ">create_Time=#{createTime},</if></set>where id=#{id}</update>
StuMapper类(前面写的注解删掉)
/*** 修改记录*/void updateStu(Student s);
MyTest(测试类),测试只修改ID为1的姓名字段
/*** 根据ID修改记录*/@Testpublic void updateStu(){Student s = new Student();s.setId(1);s.setName("加缪——修改后");stuMapper.updateStu(s);}
执行程序,达到了预期结果。

需要注意以下两点
a. 不要在set标签里面写注释,程序执行时会把注释也当做SQL语句的内容的,所以程序会报错;

b. set标签里面的每一个修改语句,末尾都要加一个英文逗号(,)
(4)删除数据:
StuMapper.xml文件
<!--4.删除数据--><delete id="deleteStu">delete from tb_stu where id=#{id}</delete>
StuMapper类(前面写的注解删掉)
/*** 根据ID删除记录*/void deleteStu(Integer id);
MyTest(测试类),测试删除ID为1的记录
/*** 根据ID删除记录*/@Testpublic void deleteStu(){Integer id = 1;stuMapper.deleteStu(id);}


小结
使用xml方式的where(条件查找)、set、if标签,可以完成一些复杂的SQL语句,另外,使用include标签,可以将重复的SQL语句抽取出来,给其他的语句复用。
如我们查询所有语句,使用全字段id,name,gender,age,create_time比使用*效率高,我们就可以把这部分抽出来。
<!--定义SQL片段--><sql id="selectAll">select id,name,gender,age,create_time</sql><!--1.查找所有--><select id="findAll" resultType="com.essay.domain.Student"><include refid="selectAll"></include>from tb_stu</select>
需要注意,写在sql片段内的SQL语句末尾不要加分号(建议xml内的所有语句末尾都不要加分号)。因为分号表示语句结束,加了分号被其他操作引用时,其他语句操作都会失效。

总结
(1)如果执行过程中出现以下异常,排查方向如下:
空指针异常:(1)检查数据库配置文件;(2)检查依赖注入和控制反转相关的注解
SQL异常:检查注解和xml文件中的SQL语句是否有错误
(2)关于注解方式和xml方式的选择,在MyBatis中文官网(https://mybatis.net.cn/getting-started.html)中有段话,值得参考。

相关文章:
MyBatis操作数据库实现
说明:MyBatis是作用于三层架构开发,数据访问层(Data Access Object)的框架,用于访问数据库,对数据进行操作。 一、环境搭建 首先,创建一个SpringBoot模块,然后把MyBatis的环境搭建…...
Git GitLab 使用及规范
Git 基本操作 Git安装配置及基本使用 从官网下载安装包,手动完成安装。打开Git Bash命令行工具,执行命令ssh-keygen -t rsa -C Email-Addresss生成一个密钥对。登录到GitLab,点击右上角你的用户头像,点击Edit Profile settings&…...
【SpringCloud——Sentinel】
一、什么是雪崩? 微服务调用链路中的某个服务发生故障,引起整个链路中的所有微服务都不可用,这就是雪崩。 二、解决雪崩问题的常见措施 1、超时处理 设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休…...
面试专题:计算机网络常见面试点总结
socket、tcp、udp、http 的认识及区别 socket、tcp、udp、http 的认识及区别 一、先来一个讲TCP、UDP和HTTP关系的 1、TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 在传…...
PageHelper失效问题
问题出现记录: 修改代码后,出现分页失效问题,原本的代码再设置了 PageHelper.startPage(pageNum, pageSize);后只有一个mysql查询,我在原本的业务查询前,新增了其他的Mysql查询,导致原需要分页的查询失效 …...
Linux常用命令——grep命令
在线Linux命令查询工具 grep 强大的文本搜索工具 补充说明 grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本&…...
学校热水供应系统方案
学校热水供应系统是现代化校园建设的重要组成部分。一套高效、可靠、安全、环保的热水供应系统,不仅能够满足学生、教职工的日常生活需求,也能提高学校形象和竞争力。 在设计学校热水供应系统方案时,需要考虑以下几个方面: 一、热…...
chatgpt赋能python:Python怎么写绝对值
Python怎么写绝对值 在Python编程语言中,有很多常用函数。其中包括求绝对值的函数。在这篇文章中,我们将介绍如何在Python中使用绝对值函数,并提供一些示例。 什么是绝对值函数? 绝对值函数是一个数学中常用的函数,…...
研发工程师玩转Kubernetes——Node亲和性requiredDuringSchedulingIgnoredDuringExecution几种边界实验
在《研发工程师玩转Kubernetes——使用Node特性定向调度Pod》中,我们提到requiredDuringSchedulingIgnoredDuringExecution只有在规则被满足的时候才能执行调度。本节我们将测试几种边界情况,看看Kubernetes的行为。 没有满足的条件 假设我们测试的Nod…...
OpenCV中的图像处理3.9(六)轮廓线特征与属性
目录 3.9 OpenCV中的轮廓线3.9.1 轮廓线:入门目标什么是轮廓线?如何绘制轮廓线?轮廓线逼近法 3.9.2 轮廓线的特征1. 矩2. 轮廓线面积3. 轮廓线周长4. 轮廓逼近5. 凸面体6. 检查凸性7. 边界矩形8. 最小包围圈9. 拟合椭圆10. 拟合直线 3.9.3 轮…...
burpsuite+xray实现联动测试(手动分析和自动化测试同时进行)
目的:安全测试过程中手动分析测试与xray自动化扫描测试结合,这样可以从多层保障安全测试的分析,针对平台业务接口量大的安全测试是十分有用的,可以实现双向测试同时开始。 xray简介 xray 是一款功能强大的安全评估工具ÿ…...
2023年专业连锁行业研究报告
第一章 行业概况 专业连锁行业是指以连锁经营模式运营的公司,其主要业务涵盖零售、餐饮、酒店、医疗、教育等领域。这些公司通过规模化、标准化的经营模式和供应链管理,提供专业化、高质量的产品和服务。专业连锁行业在全球范围内蓬勃发展,并…...
Mysql数据库(六):基本的SELECT语句
基本的SELECT语句 前言一、SELECT...二、SELECT ... FROM三、列的别名四、去除重复行五、空值参与运算六、着重号七、查询常数八、显示表结构九、过滤数据 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主&#…...
在CentOS7环境中,实现使用openresty配置文件,达到jwt指定用户userid不能访问的效果
#在CentOS7环境中,实现使用openresty配置文件,达到jwt指定用户userid不能访问的效果。 首先,你需要安装 OpenResty 和 JWT 组件: 安装 OpenResty 参考 OpenResty 的官方安装文档,在终端执行如下命令: $…...
SpringBoot 源码分析初始化应用上下文(1)-createApplicationContext
前言:springBoot的版本是 2.2.4.RELEASE 一、入口 /*** Run the Spring application, creating and refreshing a new* {link ApplicationContext}.* param args the application arguments (usually passed from a Java main method)* return a running {link A…...
STM32队列
目录 什么是队列? 队列特点 1. 数据入队出队方式 2. 数据传递方式 3. 多任务访问 4. 出队、入队阻塞 队列相关 API 函数 1. 创建队列 参数: 2. 写队列 参数: 返回值: 3. 读队列 参数: 返回值…...
探索Beyond Compare:让文件比较和管理变得简单高效
在这个信息爆炸时代,我们的日常生活和工作中需要处理大量的数据和文档。在这个过程中,有时候我们会面临找出不同文件之间的差异、合并重复内容等需求。那么,有没有一款软件可以帮助我们轻松地完成这些任务呢?答案当然是肯定的&…...
动态网站Servelt基础
文章目录 一、Servlet基础(一)Servlet概述1、Servlet是什么2、Servlet容器3、Servlet应用程序的体系结构 (二)Servlet的特点1、功能强大2、可移植3、性能高效4、安全性高5、可扩展 (三)Servlet接口1、Servl…...
Docker 网络
Docker 网络实现原理 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机…...
Tomcat的优化
Tomcat的优化 一、Tomcat 优化Tomcat 配置文件参数优化 二、系统内核优化三、Tomcat 配置 JVM 参数:参数含义 一、Tomcat 优化 Tomcat默认安装下的缺省配置并不适合生产环境,它可能会频繁出现假死现象需要重启,只有通过不断压测优化才能让它…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
