【数据库系列】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是五个设计原则的首字母…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
