【数据库系列】Spring Boot 中使用 MyBatis 详细指南
一、基础介绍
1.1 MyBatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJO(Plain Old Java Objects)映射成数据库中的记录。
1.2 Spring Boot 集成 MyBatis 的优势
将 Spring Boot 和 MyBatis 集成,能够充分发挥 Spring Boot 的快速开发特性和 MyBatis 灵活的数据库操作能力。通过这种集成,可以快速搭建一个稳定、高效的数据库访问层,简化开发流程,提高开发效率。
二、集成步骤
2.1 创建 Spring Boot 项目
可以使用 Spring Initializr(https://start.spring.io/)来快速创建一个 Spring Boot 项目。在创建项目时,需要选择以下依赖:
- Spring Web
- Spring Data JPA
- MySQL Driver
- MyBatis Framework
2.2 配置数据源
在 application.properties
文件中配置数据库连接信息:
spring.datasource.url=jdbc:mysql://localhost:3306/yourdatabase
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2.3 配置 MyBatis
在 application.properties
文件中配置 MyBatis 的相关属性:
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.type-aliases-package=com.example.demo.entity
mybatis.mapper-locations
配置 MyBatis 映射文件的位置,mybatis.type-aliases-package
配置实体类的包名,这样在 MyBatis 映射文件中就可以直接使用实体类名而无需写全限定名。
2.4 创建实体类
创建一个 Java 实体类,用于映射数据库表中的记录。例如,创建一个 User
实体类:
package com.example.demo.entity;public class User {private Long id;private String username;private String password;// 省略 getters 和 setters
}
2.5 创建 Mapper 接口
创建一个 Mapper 接口,用于定义数据库操作方法。例如,创建一个 UserMapper
接口:
package com.example.demo.mapper;import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface UserMapper {@Select("SELECT * FROM user")List<User> findAll();
}
@Mapper
注解用于将该接口标记为 MyBatis 的 Mapper 接口。
2.6 创建 Mapper 映射文件
在 resources/mapper
目录下创建一个 UserMapper.xml
文件,用于实现 Mapper 接口中的方法:
<?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.demo.mapper.UserMapper"><select id="findAll" resultType="com.example.demo.entity.User">SELECT * FROM user</select>
</mapper>
namespace
属性指定 Mapper 接口的全限定名,id
属性指定要实现的方法名,resultType
属性指定返回结果的类型。
2.7 创建 Service 层
创建一个 Service 层,用于调用 Mapper 接口中的方法。例如,创建一个 UserService
接口和其实现类 UserServiceImpl
:
package com.example.demo.service;import com.example.demo.entity.User;import java.util.List;public interface UserService {List<User> findAll();
}
package com.example.demo.service.impl;import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> findAll() {return userMapper.findAll();}
}
2.8 创建 Controller 层
创建一个 Controller 层,用于处理客户端请求。例如,创建一个 UserController
:
package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic List<User> findAll() {return userService.findAll();}
}
三、示例完整代码
1. 创建 application.yml
在 src/main/resources
目录下创建 application.yml
文件。
2. 配置数据源和 MyBatis
将原本 application.properties
中的配置内容转换为 YAML 格式,如下:
spring:datasource:url: jdbc:mysql://localhost:3306/yourdatabaseusername: yourusernamepassword: yourpassworddriver-class-name: com.mysql.cj.jdbc.Driver
mybatis:mapper-locations: classpath:/mapper/*.xmltype-aliases-package: com.example.demo.entity
说明
- 在 YAML 中,使用缩进表示层级关系。例如,
spring
和mybatis
是顶级配置项,datasource
是spring
的子配置项,url
、username
、password
和driver-class-name
是datasource
的子配置项。 - 冒号后面需要跟一个空格,然后再写具体的值。
完整项目示例
以下是基于上述 application.yml
配置的完整项目示例,包括之前提到的各个部分:
项目结构
src
├── main
│ ├── java
│ │ ├── com
│ │ │ ├── example
│ │ │ │ ├── demo
│ │ │ │ │ ├── controller
│ │ │ │ │ │ └── UserController.java
│ │ │ │ │ ├── entity
│ │ │ │ │ │ └── User.java
│ │ │ │ │ ├── mapper
│ │ │ │ │ │ ├── UserMapper.java
│ │ │ │ │ │ └── UserMapper.xml
│ │ │ │ │ ├── service
│ │ │ │ │ │ ├── UserService.java
│ │ │ │ │ │ └── impl
│ │ │ │ │ │ └── UserServiceImpl.java
│ │ │ │ │ └── DemoApplication.java
│ └── resources
│ ├── application.yml
│ └── mapper
│ └── UserMapper.xml
└── test└── java└── com└── example└── demo└── DemoApplicationTests.java
依赖配置(pom.xml)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
实体类(User.java)
package com.example.demo.entity;public class User {private Long id;private String username;private String password;// 构造函数public User() {}public User(String username, String password) {this.username = username;this.password = password;}// getters 和 setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
Mapper 接口(UserMapper.java)
package com.example.demo.mapper;import com.example.demo.entity.User;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserMapper {@Select("SELECT * FROM user")List<User> findAll();@Select("SELECT * FROM user WHERE id = #{id}")User findById(Long id);@Insert("INSERT INTO user (username, password) VALUES (#{username}, #{password})")@Options(useGeneratedKeys = true, keyProperty = "id")void save(User user);@Update("UPDATE user SET username = #{username}, password = #{password} WHERE id = #{id}")void update(User user);@Delete("DELETE FROM user WHERE id = #{id}")void delete(Long id);
}
Mapper 映射文件(UserMapper.xml)
<?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.demo.mapper.UserMapper"><select id="findAll" resultType="com.example.demo.entity.User">SELECT * FROM user</select><select id="findById" resultType="com.example.demo.entity.User">SELECT * FROM user WHERE id = #{id}</select><insert id="save" keyProperty="id" useGeneratedKeys="true">INSERT INTO user (username, password) VALUES (#{username}, #{password})</insert><update id="update">UPDATE user SET username = #{username}, password = #{password} WHERE id = #{id}</update><delete id="delete">DELETE FROM user WHERE id = #{id}</delete>
</mapper>
Service 层
UserService.java
package com.example.demo.service;import com.example.demo.entity.User;import java.util.List;public interface UserService {List<User> findAll();User findById(Long id);void save(User user);void update(User user);void delete(Long id);
}
UserServiceImpl.java
package com.example.demo.service.impl;import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> findAll() {return userMapper.findAll();}@Overridepublic User findById(Long id) {return userMapper.findById(id);}@Overridepublic void save(User user) {userMapper.save(user);}@Overridepublic void update(User user) {userMapper.update(user);}@Overridepublic void delete(Long id) {userMapper.delete(id);}
}
Controller 层(UserController.java)
package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic ResponseEntity<List<User>> findAll() {List<User> users = userService.findAll();return new ResponseEntity<>(users, HttpStatus.OK);}@GetMapping("/{id}")public ResponseEntity<User> findById(@PathVariable Long id) {User user = userService.findById(id);if (user!= null) {return new ResponseEntity<>(user, HttpStatus.OK);} else {return new ResponseEntity<>(HttpStatus.NOT_FOUND);}}@PostMappingpublic ResponseEntity<Void> save(@RequestBody User user) {userService.save(user);return new ResponseEntity<>(HttpStatus.CREATED);}@PutMappingpublic ResponseEntity<Void> update(@RequestBody User user) {userService.update(user);return new ResponseEntity<>(HttpStatus.NO_CONTENT);}@DeleteMapping("/{id}")public ResponseEntity<Void> delete(@PathVariable Long id) {userService.delete(id);return new ResponseEntity<>(HttpStatus.NO_CONTENT);}
}
测试(DemoApplicationTests.java)
package com.example.demo;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
public class DemoApplicationTests {@Autowiredprivate UserService userService;@Testpublic void testFindAll() {assertEquals(0, userService.findAll().size());}@Testpublic void testSaveAndFindById() {User user = new User("testuser", "testpassword");userService.save(user);assertNotNull(userService.findById(user.getId()));}@Testpublic void testUpdate() {User user = new User("testuser", "testpassword");userService.save(user);user.setPassword("newpassword");userService.update(user);assertEquals("newpassword", userService.findById(user.getId()).getPassword());}@Testpublic void testDelete() {User user = new User("testuser", "testpassword");userService.save(user);userService.delete(user.getId());assertNull(userService.findById(user.getId()));}
}
通过上述配置和代码示例,你可以在 Spring Boot 项目中使用 application.yml
配置文件来集成 MyBatis,并实现完整的用户管理功能。
相关文章:

【数据库系列】Spring Boot 中使用 MyBatis 详细指南
一、基础介绍 1.1 MyBatis MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 P…...

Azure Airflow 中配置错误可能会使整个集群受到攻击
网络安全研究人员在 Microsoft 的 Azure 数据工厂 Apache Airflow 中发现了三个安全漏洞,如果成功利用这些漏洞,攻击者可能会获得执行各种隐蔽操作的能力,包括数据泄露和恶意软件部署。 “利用这些漏洞可能允许攻击者以影子管理员的身份获得…...

Python跨年烟花
目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…...
【代码】Python|Windows 批量尝试密码去打开加密的 Word 文档(docx和doc)
文章目录 前言完整代码Githubdocxdoc 代码解释1. msoffcrypto 方法(用于解密 .docx 文件)read_secret_word_file 函数密码生成与解密尝试try_decrypt_file 函数 2. comtypes 方法(用于解密 .doc 文件)read_secret_word_file 函数注…...
java开发中注解汇总
注解作用位置注意mybatis Data Getter Setter ToString EqualsAndHashCode AllArgsConstructor NoArgsConstructor Data 代替:无参构造,get,set,toString,hashCode,equals Getter Setter 可放在类和方法上&…...
C# 设计模式(结构型模式):外观模式
C# 设计模式(结构型模式):外观模式 (Facade Pattern) 在复杂系统中,往往会涉及到多个子系统、模块和类。这些子系统的接口和功能可能会让使用者感到困惑和复杂。在这种情况下,我们可以使用外观模式(Facade…...

PowerShell 常见问题解答
PowerShell 是微软开发的一种功能强大的命令行界面和脚本语言,广泛应用于系统管理和自动化任务。以下是一些使用 PowerShell 时常见的问题及其解决方法。 什么是 PowerShell? PowerShell 是基于 .NET 的命令行界面(CLI)和脚本语言…...

计算机网络 (15)宽带接入技术
前言 计算机网络宽带接入技术是指通过高速、大容量的通信信道或网络,实现用户与互联网或其他通信网络之间的高速连接。 一、宽带接入技术的定义与特点 定义:宽带接入技术是指能够传输大量数据的通信信道或网络,其传输速度通常较高,…...
前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
《写给前端的python应用指南》系列: (一)快速构建 Web 服务器 - Flask vs Node.js 对比(二)深入Flask:理解Flask的应用结构与模块化设计(三)Django vs Flask:哪种框架适…...
【Unity3D】基于UGUI——简易版 UI框架
https://github.com/AMikeW/BStandShaderResources/blob/master/milk_UIFramework.unitypackage UI框架支持如下功能: 1、层级控制 2、支持面板多次打开时,隐藏前一个打开的面板,当关闭面板时,能够恢复前一个打开面板状态 3、支…...
算法排序算法
文章目录 快速排序[leetcode 215数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/)分析题解快速排序 桶排序[leetcode 347 前K个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/)分析题解 快速排序 leetcode 215数组…...
第3章 总线
总线的定义 为多个部件 分时共享 公共信息传送线路。 系统之间、模块之间、芯片内部用来传递信息信号线集合。 共享 总线上可连接多个部件 各部件间相互交换信息 都可通过总线来。 分时 同一时刻 总线上只能传 一个部件信息。 采用标准总线的优点 简化系统软硬件设计 从硬件角度…...

手机实时提取SIM卡打电话的信令声音-双卡手机来电如何获取哪一个卡的来电
手机实时提取SIM卡打电话的信令声音 --双卡手机来电如何获取哪一个卡的来电 一、前言 前面的篇章《手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案》中,我们论述了局域网SIP坐席通过手机外呼出去时,手机中主副卡的呼叫调度策略。 但…...
共阳极LED的控制与短路问题解析
共阳极LED的控制与短路问题解析 在电子电路中,LED(发光二极管)是最常见的元件之一。LED的连接方式分为共阳极和共阴极,不同的连接方式决定了LED的控制逻辑。本文将重点讲解共阳极LED的工作原理,并解答“为什么给1不会…...

华为消费级QLC SSD来了
近日,有关消息显示,华为的消费级SSD产品线,eKitStor Xtreme 200E系列,在韩国一家在线零售商处首次公开销售,引起了业界的广泛关注。 尽管华为已经涉足服务器级别的SSD制造多年,但直到今年6月才正式推出面向…...

liunx下载gitlab
1.地址: https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装 postfix 并启动 yum install postfix systemctl start postfix systemctl enable postfix ssh服务启动 systemctl enable sshd systemctl start sshd开放 ssh 以及 http 服务,…...

深度学习模型预测值集中在某一个值
深度学习模型,训练过程中,经常遇到预测的结果集中在某个值,而且在学习的过程中会变,样例如下。 主要有如下解决方案 1、更换relu ->tanh 或者其他激活函数 2、更改随机种子,估计是没有初始化好,或者调…...

Sqoop的使用
每个人的生活都是一个世界,即使最平凡的人也要为他那个世界的存在而战斗。 ——《平凡的世界》 目录 一、sqoop简介 1.1 导入流程 1.2 导出流程 二、使用sqoop 2.1 sqoop的常用参数 2.2 连接参数列表 2.3 操作hive表参数 2.4 其它参数 三、sqoop应用 - 导入…...
OpenGL ES 04 图片数据是怎么写入到对应纹理单元的
从指定路径加载图像并转换为 CGImage。获取图像的宽度和高度。创建一个 RGB 颜色空间。为图像数据分配内存。创建一个位图上下文并将图像绘制到上下文中。创建一个新的纹理对象并绑定到指定的纹理单元。指定二维纹理图像。释放分配的内存。设置纹理参数,包括放大和缩…...
C# 设计模式的六大原则(SOLID)
C# 设计模式的六大原则(SOLID) 引言 在面向对象编程中,设计模式提供了高效、可复用和可维护的代码结构。SOLID原则是软件设计中的一组重要原则,用于确保代码具有良好的可维护性、可扩展性和灵活性。SOLID是五个设计原则的首字母…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...