在Spring Boot中使用MyBatis访问数据库
MyBatis,这个对各位使用Java开发的开发者来说还是蛮重要的,我相信诸位在企业开发项目的时候,大多数采用的是Mybatis。使用MyBatis帮助我们解决各种问题,实际上这篇文章,基本上默认为可以跳过的一篇,但是为了Spring Boot的系列,我还是写了这篇文章。
MyBatis
作为一个在Hibernate之后出现的持久层框架,因为他支持自定义SQL,存储过程以及高级映射,MyBatis免除了几乎所有的JDBC代码,以及设置参数和获取结果集的工作。MyBatis可以通过简单的XML或者注解来配置和映射原始类型,接口,和Java POJO为数据库中记录。
MyBatis官网: https://mybatis.org/mybatis-3/zh/index.html
引入依赖
<!--MyBatis依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.oracle.ojdbc</groupId><artifactId>ojdbc8</artifactId><version>19.3.0.0</version><scope>compile</scope></dependency>
这里说明一下,MyBatis的版本和Java JDK和Spring Boot的版本是有要求的:
2.1.x
版本适用于:MyBatis 3.5+、Java 8+、Spring Boot 2.1+
2.0.x
版本适用于:MyBatis 3.5+、Java 8+、Spring Boot 2.0/2.1
1.3.x
版本适用于:MyBatis 3.4+、Java 6+、Spring Boot 1.5
配置Application文件
接下来,我们配置Spring Boot的自带的application配置文件:
# MySQL
#spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
#spring.datasource.username=root
#spring.datasource.password=123456
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverserver.port=1001
# Oracle
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/orcl
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
这是我的Oracle表结构:
MySQL表结构:
CREATE TABLE `User` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL,`age` int DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
接下来创建User表的映射对象,也是我们通用的实体类对象:
public class User {private Long id;private String name;private Integer age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}public User(String name, Integer age) {this.name = name;this.age = age;}public User() {}
}
在有了实体类对象,并且和数据库的字段一一对应后,就可以在接口红定义相关对数据库表的操作了,这里举例,一个是查询,一个是插入,用于后续单元测试的验证。
@Mapper
public interface UserMapper {@Select("SELECT * FROM USER WHERE NAME = #{name}")User findByName(@Param("name") String name);@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);}
接下来创建一个单元测试类,插入一条数据,然后利用这条数据的相关属性进行查询,并且判断相关属性是否满足。
注意,测试结束后,对数据进行回滚操作,保证单元测试每次运行的数据环境独立。
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class ApplicationTests {@Autowiredprivate UserMapper userMapper;@Test@Rollbackpublic void test() throws Exception {userMapper.insert("AAA", 20);User u = userMapper.findByName("AAA");Assert.assertEquals(20, u.getAge().intValue());}}
对于注解配置进行说明介绍
@Mapper
:用于标注Mapper接口,表示该接口是MyBatis的Mapper映射接口。在Spring Boot项目中,可以使用@MapperScan
注解扫描指定包下的Mapper接口,并将其注册为Bean。
@Select
:用于标注查询语句,指定SQL语句或调用Mapper XML文件中的对应SQL语句。可以通过value属性指定SQL语句,也可以通过provider属性指定动态SQL提供者类。
@Insert
、@Update
、@Delete
:分别用于标注插入、更新和删除语句,使用方式与@Select
类似。
@Result
、@Results
:用于标注结果集映射关系。@Result用于标注单个字段或属性与结果集列的映射关系,@Results用于标注多个@Result。
@Param
:用于标注方法参数,指定参数在SQL语句中的名称。在SQL语句中可以通过#{参数名}的方式引用该参数。
@Options
:用于配置一些选项,例如设置主键生成策略、返回自增主键等。
@ResultMap
:用于标注结果集映射配置的ID,可以在其他地方通过@ResultMap引用该结果集映射。
@One
、@Many
:用于标注一对一和一对多的关联关系。
@CacheNamespace
:用于开启二级缓存,将Mapper的查询结果缓存到内存中,提高查询性能。
注解 | 使用对象 | 相对应的 XML | 描述 |
---|---|---|---|
@Insert @Update @Delete @Select | 方法 | <insert><update><delete><select> | 这四个注解分别代表将会被执行的 SQL 语句。它们用字符串数组(或单个字符串)作为参数。如果传递的是字符串数组,字符串之间先会被填充一个空格再连接成单个完整的字符串。这有效避免了以 Java 代码构建 SQL 语句时的“丢失空格”的问题。然而,你也可以提前手动连接好字符串。属性有:value,填入的值是用来组成单个 SQL 语句的字符串数组。 |
@Options | 方法 | 映射语句的属性 | 这个注解提供访问大范围的交换和配置选项的入口,它们通常在映射语句上作为属性出现。Options 注解提供了通俗易懂的方式来访问它们,而不是让每条语句注解变复杂。属性有:useCache=true, flushCache=FlushCachePolicy.DEFAULT, resultSetType=FORWARD_ONLY, statementType=PREPARED, fetchSize=-1, timeout=-1, useGeneratedKeys=false, keyProperty="id", keyColumn="", resultSets="" 。值得一提的是, Java 注解无法指定 null 值。因此,一旦你使用了 Options 注解,你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的预期以外的行为。注意: keyColumn 属性只在某些数据库中有效(如 Oracle、PostgreSQL等)。请在插入语句一节查看更多关于 keyColumn 和 keyProperty 两者的有效值详情。 |
@MapKey | 方法 | – | 这是一个用在返回值为 Map 的方法上的注解。它能够将存放对象的 List 转化为 key 值为对象的某一属性的 Map。属性有: value,填入的是对象的属性名,作为 Map 的 key 值。 |
@SelectKey | 方法 | <selectKey> | 这个注解的功能与 <selectKey> 标签完全一致,用在已经被 @Insert 或 @InsertProvider 或 @Update 或 @UpdateProvider 注解了的方法上。若在未被上述四个注解的方法上作 @SelectKey 注解则视为无效。如果你指定了 @SelectKey 注解,那么 MyBatis 就会忽略掉由 @Options 注解所设置的生成主键或设置(configuration)属性。属性有:statement 填入将会被执行的 SQL 字符串数组,keyProperty 填入将会被更新的参数对象的属性的值,before 填入 true 或 false 以指明 SQL 语句应被在插入语句的之前还是之后执行。resultType 填入 keyProperty 的 Java 类型和用 Statement、 PreparedStatement 和 CallableStatement 中的 STATEMENT、 PREPARED 或 CALLABLE 中任一值填入 statementType。默认值是 PREPARED。 |
@Param | 参数 | N/A | 如果你的映射方法的形参有多个,这个注解使用在映射方法的参数上就能为它们取自定义名字。若不给出自定义名字,多参数(不包括 RowBounds 参数)则先以 “param” 作前缀,再加上它们的参数位置作为参数别名。例如 #{param1}, #{param2},这个是默认值。如果注解是 @Param(“person”),那么参数就会被命名为 #{person}。 |
@InsertProvider @UpdateProvider @DeleteProvider @SelectProvider | 方法 | <insert> <update> <delete> <select> | 允许构建动态 SQL。这些备选的 SQL 注解允许你指定类名和返回在运行时执行的 SQL 语句的方法。(自从MyBatis 3.4.6开始,你可以用 CharSequence 代替 String 来返回类型返回值了。)当执行映射语句的时候,MyBatis 会实例化类并执行方法,类和方法就是填入了注解的值。你可以把已经传递给映射方法了的对象作为参数,“Mapper interface type” 和 “Mapper method” 会经过 ProviderContext (仅在MyBatis 3.4.5及以上支持)作为参数值。(MyBatis 3.4及以上的版本,支持多参数传入)属性有: type, method。type 属性需填入类。method 需填入该类定义了的方法名。注意 接下来的小节将会讨论类,能帮助你更轻松地构建动态 SQL。 |
这里就围绕@Param,Map聊聊。
@Param
我们在实际开发过程中,如果将SQL语句嵌套在接口的时候,我们经常使用的方式就是这种:
@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
int insert(@Param("name") String name, @Param("age") Integer age);
这种方式,我们都很少理解,@Param中定义的name对应了SQL中的#{name},age
对应了SQL中的#{age}。
Map
除了以@Param注入,我们也可以通过Map<String,Object>
对象作为传递参数的容器:
@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})")
int insertByMap(Map<String, Object> map);
得到如上代码,那么我们应该如何注入呢?
Map<String, Object> map = new HashMap<>();
map.put("name", "CCC");
map.put("age", 40);
userMapper.insertByMap(map);
如上,我们通过对map中填入同名的内容就可以实现了。
使用对象注入
除去Map方式注入值外,我们也可以直接java对象直接作为查询条件的传参,比如我们可以直接使用User对象:
@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
int insertByUser(User user);
利用MyBatis实现增删改查
MyBatis针对不同的数据库操作,分别提供了不同的注解进行配置:
public interface UserMapper {@Select("SELECT * FROM user WHERE name = #{name}")User findByName(@Param("name") String name);@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);@Update("UPDATE user SET age=#{age} WHERE name=#{name}")void update(User user);@Delete("DELETE FROM user WHERE id =#{id}")void delete(Long id);
}
之后我们可以利用创建一个Test测试类,来实现我们的功能是否正常实现:
@Transactional
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprivate UserMapper userMapper;@Test@Rollbackpublic void testUserMapper() throws Exception {// insert一条数据,并select出来验证userMapper.insert("AAA", 20);User u = userMapper.findByName("AAA");Assert.assertEquals(20, u.getAge().intValue());// update一条数据,并select出来验证u.setAge(30);userMapper.update(u);u = userMapper.findByName("AAA");Assert.assertEquals(30, u.getAge().intValue());// 删除这条数据,并select验证userMapper.delete(u.getId());u = userMapper.findByName("AAA");Assert.assertEquals(null, u);}
}
返回结果绑定
对于增、删、改操作相对的数据也就变化较小,但是对于查我们就需要考虑的比较多了,怎么查,多表查,子查,并且查询的结果也不在是我们经常碰到的实体类对象了,往往需要返回一个与数据库实体不同的包装类,那么对于这样的情况,我们可以通过@Result和@Result注解进行绑定。
@Results({@Result(property = "name", column = "name"),@Result(property = "age", column = "age")
})
@Select("SELECT name, age FROM user")
List<User> findAll();
@Result
中的property属性对应User对象中的成员名,column对应SELECT出的字段名。在该配置中故意没有查出id属性,只对User对应中的name和age对象做了映射配置,这样可以通过下面的单元测试来验证查出的id为null,而其他属性不为null:
@Test
@Rollback
public void testUserMapper() throws Exception {List<User> userList = userMapper.findAll();for(User user : userList) {Assert.assertEquals(null, user.getId());Assert.assertNotEquals(null, user.getName());}
}
相关文章:

在Spring Boot中使用MyBatis访问数据库
MyBatis,这个对各位使用Java开发的开发者来说还是蛮重要的,我相信诸位在企业开发项目的时候,大多数采用的是Mybatis。使用MyBatis帮助我们解决各种问题,实际上这篇文章,基本上默认为可以跳过的一篇,但是为了…...
懒羊羊闲话2
前言: 笔者谈不上是某个领域的高手,也不是大厂的某个神秘高手,一直游离于小型公司,写下这篇文章献给那些无法接触到好的学习环境,苦恼自己原地踏步的coder。 1、如何快速熟悉某个行业 作为一个编码多年的程序员&#…...

多路转接(上)——select
目录 一、select接口 1.认识select系统调用 2.对各个参数的认识 二、编写select服务器 1.两个工具类 2.网络套接字封装 3.服务器类编写 4.源文件编写 5.运行 一、select接口 1.认识select系统调用 int select(int nfds, fd_set readfds, fd_set writefds, fd_set ex…...

基于SSM的图书管理借阅系统设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...
Python的内存优化
在Python中,内存管理和优化是一个复杂的话题,因为它涉及到Python解释器的内部机制,特别是Python的垃圾收集和内存分配策略。Python通过自动垃圾收集机制管理内存,主要包括引用计数和标记-清除算法。 Python内存管理机制ÿ…...
蓝桥杯-回文日期[Java]
目录: 学习目标: 学习内容: 学习时间: 题目: 题目描述: 输入描述: 输出描述: 输入输出样例: 示例 1: 运行限制: 题解: 思路: 学习目标: 刷蓝桥杯题库日记 学习内容: 编号498题目回文日期难度…...
acwing算法基础之搜索与图论--树与图的遍历
目录 1 基础知识2 模板3 工程化 1 基础知识 树和图的存储:邻接矩阵、邻接表。 树和图的遍历:dfs、bfs。 2 模板 树是一种特殊的图(即,无环连通图),与图的存储方式相同。 对于无向图中的边ab,…...
前端uniapp请求真是案例(带源码)
目录 案例一案例二最后 案例一 <template><view class"box"><!-- <view class"title-back" click"backPrivious"><</view> --><!-- <view class"title-back" click"backPrivious"…...

MySQL -- mysql connect
MySQL – mysql connect 文章目录 MySQL -- mysql connect一、Connector/C 使用1.环境安装2.尝试链接mysql client 二、MySQL接口1.初始化2.链接数据库3.下发mysql命令4.获取执行结果5.关闭mysql链接6.在C语言中连接MySQL 三、MySQL图形化界面推荐 使用C接口库来进行连接 一、…...
如何用AI帮你下载安卓源码
以Android 11源码下载流程图如下所示: 1. 安装Git和Repo工具 2. 创建一个工作目录 3. 初始化仓库并下载源码 4. 切换到指定的分支 5. 编译源码 具体步骤如下: 安装Git和Repo工具:在Linux或Mac上,可以通过终端运行以下命令安装Gi…...

第三章:人工智能深度学习教程-基础神经网络(第三节-Tensorflow 中的多层感知器学习)
在本文中,我们将了解多层感知器的概念及其使用 TensorFlow 库在 Python 中的实现。 多层感知器 多层感知也称为MLP。它是完全连接的密集层,可将任何输入维度转换为所需的维度。多层感知是具有多个层的神经网络。为了创建神经网络,我们将神…...

Python的版本如何查询?
要查询Python的版本,可以使用以下方法之一: 1.在命令行中使用python --version命令。这会显示安装在计算机上的Python解释器的版本号。 # Author : 小红牛 # 微信公众号:wdPython2.在Python脚本中使用import sys语句,然后打印sy…...

Git的高效使用 git的基础 高级用法
Git的高效使用 git的基础 高级用法 前言 什么是Git 在日常的软件开发过程中,软件版本的管理都离不开使用Git,Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linu…...
关于主表和子表数据的保存
业务需求: 投注站信息保存在表A里,投注站下的设备信息保存在表B里, 一个投注站会有多个设备,要在一个表单里进行投注站和设备信息的填写,保存,回填,修改。 思路: 1)将…...

如何在后台执行 SwiftData 操作
文章目录 前言Core Data 私有队列上下文SwiftData 并发支持使用 ModelActor合并上下文更改的问题通过标识符访问模型总结 前言 SwiftData 是一个用于处理数据操作的框架,特别是在 Swift 语言中进行并发操作。本文介绍了如何在后台执行 SwiftData 操作以及与 Core D…...

TCP和UPD协议
一)应用层协议简介:根据需求明确要传输的信息,明确要传输的数据格式; 应用层协议:这个协议,实际上是和程序员打交道最多的协议了 1)其它四层都是操作系统,驱动,硬件实现好了的,咱们是不需要管 2)应用层:当我…...

MySQL:锁机制
目录 概述三种层级的锁锁相关的 SQLMyISAM引擎下的锁InnoDB引擎下的锁InnoDB下的表锁和行锁InnoDB下的共享锁和排他锁InnoDB下的意向锁InnoDB下的记录锁,间隙锁,临键锁记录锁(Record Locks)间隙锁(Gap Locks࿰…...

软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】
软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】 课本里章节里所有蓝色字体的思维导图...

【Git】安装和常用命令的使用与讲解及项目搭建和团队开发的出现的问题并且给予解决
目录 Git的简介 介绍 Git的特点及概念 Git与SVN的区别 图解 编辑 命令使用 安装 使用前准备 搭建项目环境 编辑 团队开发 Git的简介 介绍 Git 是一种分布式版本控制系统,是由 Linux 之父 Linus Torvalds 于2005年创建的。Git 的设计目标是为了更好地管…...

Python进行数据可视化,探索和发现数据中的模式和趋势。
文章目录 前言第一步:导入必要的库第二步:加载数据第三步:创建基本图表第四步:添加更多细节第五步:使用Seaborn库创建更复杂的图表关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Pyth…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...