SpringBoot从入门到精通-第15章 MyBatis框架
学习MyBatis心路历程
2022年学习java基础时候,想着怎么使用java代码操作数据库,咨询了项目上开发W同事,没有引用框架,操作数据库很麻烦,就帮我写好多行代码,就实现了一个查询语句,至今我也忘记了那些代码大概是个什么样。
2025年果断入手一本SpringBoot从入门到精通纸质版书,纸质版书籍个人理解:
- 1、有版权,案例有保障;
- 2、系统性,把前后顺序会设计好;
- 3、想翻的时候,翻起来有感觉;
- 4、就是案例比较单一。
然后就是一看就会,一做就废。但是最终只有一个解决方案,那就是动手敲,动手实现,实现过,心里就有底,才能说服自己这个我操作过。以下是我根据案例实操的步骤和结果,展示一下吧。
一、MyBatis简介
Mybatis是一款半自动化的持久层框架,所谓半自动化,就是MyBatis不仅需要程序开发人员手动编写SQL语句,而且需要手动设置SQL语句与实体类的映射关系。
MyBatis和Hibernate
MyBatis和Hibernate都是Java领域中流行的对象关系映射(ORM)框架,它们都旨在简化数据库操作和对象模型之间的交互。尽管它们都提供了类似的解决方案,但在设计理念、使用方式、性能和灵活性等方面存在一些关键差别。
结论
选择MyBatis还是Hibernate主要取决于项目的具体需求、开发团队的偏好以及特定的项目要求。如果项目需要高度定制的SQL并且团队成员熟悉SQL,那么MyBatis可能是更好的选择。如果项目更倾向于减少直接编写SQL的需要并希望减少数据库层面的复杂性,那么Hibernate可能更合适。在实践中,很多团队也会根据项目的不同部分选择使用这两种技术的一个组合,以平衡灵活性和易用性。
二、在Spring Boot项目中整合MyBatis
0、整体结构
1、整体步骤:
- pom.xml添加MyBatis依赖
- pom.xml添加数据库驱动依赖
- application配置文件添加datasource配置项
- 创建mapper映射器
- 在SpringBoot启动类添加用于表示映射器扫描的@MapperScan(basePackages = “com.mr._20250602spring_mybatis”)注解
- 实现数据库的基本事物,即编写实体类(对应数据库表)
- 测试类编写测试方法
- 启动测试类方法测试
2、步骤附代码
- pom.xml添加MyBatis依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
- pom.xml添加数据库驱动依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<!-- <scope>runtime</scope>-->
</dependency>
- application配置文件添加datasource配置项
spring.application.name=20250602spring_mybatis
spring.datasource.url=jdbc:mysql://10.0.0.132:1588/db_video?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true
spring.datasource.username=sun
spring.datasource.password=Sun@123
整体pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- <parent>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-parent</artifactId>-->
<!-- <version>3.5.0</version>-->
<!-- <relativePath/> <!– lookup parent from repository –>-->
<!-- </parent>-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.mr</groupId>
<artifactId>_20250602spring_mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>20250602spring_mybatis</name>
<description>20250602spring_mybatis</description>
<!-- <url/>-->
<!-- <licenses>-->
<!-- <license/>-->
<!-- </licenses>-->
<!-- <developers>-->
<!-- <developer/>-->
<!-- </developers>-->
<!-- <scm>-->
<!-- <connection/>-->
<!-- <developerConnection/>-->
<!-- <tag/>-->
<!-- <url/>-->
<!-- </scm>-->
<!-- <properties>-->
<!-- <java.version>17</java.version>-->
<!-- </properties>-->
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>mysql</groupId>-->
<!-- <artifactId>mysql-connector-java</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<!-- <scope>runtime</scope>-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 创建mapper映射器
package com.mr._20250602spring_mybatis.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import com.mr._20250602spring_mybatis.pojo.T_video;
public interface EmpMapper {
// @Select("select name from t_video where id = 10")
// boolean selectAll();
@Insert("insert into t_video values(33,'springboot','sun',22)")
boolean insertData();
}
- 在SpringBoot启动类添加用于表示映射器扫描的@MapperScan(basePackages = “com.mr._20250602spring_mybatis”)注解
package com.mr._20250602spring_mybatis;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = "com.mr._20250602spring_mybatis")
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 实现数据库的基本事物,即编写实体类(对应数据库表)
package com.mr._20250602spring_mybatis.pojo;
public class T_video {
private Integer id;
private String name;
private String author;
private int video_view;
public T_video(Integer id, String name, String author, int video_view) {
this.id = id;
this.name = name;
this.author = author;
this.video_view = video_view;
}
public T_video() {
}
@Override
public String toString() {
return "T_video{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", video_view=" + video_view +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getVideo_view() {
return video_view;
}
public void setVideo_view(int video_view) {
this.video_view = video_view;
}
}
- 测试类编写测试方法
package com.mr._20250602spring_mybatis;
import com.mr._20250602spring_mybatis.mapper.EmpMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Autowired
EmpMapper mapper;
@Test
void contextLoads() {
// System.out.println("查询id=10 的name");
System.out.println("增加一条数据");
boolean result;
if (mapper.insertData()) result = true;
else result = false;
System.out.println(result);
}
}
- 启动测试类方法测试
增加一条数据
2025-06-02 08:06:34.599 INFO 12944 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2025-06-02 08:06:34.962 INFO 12944 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
true
三、SQL语句中添加占位符
package com.mr._20250602spring_mybatis.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import com.mr._20250602spring_mybatis.pojo.T_video;
public interface EmpMapper {
// @Select("select name from t_video where id = 10")
// boolean selectAll();
@Insert("insert into t_video values(33,'springboot','sun',22)")
boolean insertData();
@Select("select name from t_video where id = #{id}")
String selectAll(int id);
}
修改测试类
package com.mr._20250602spring_mybatis;
import com.mr._20250602spring_mybatis.mapper.EmpMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Autowired
EmpMapper mapper;
@Test
void contextLoads() {
// System.out.println("查询id=10 的name");
System.out.println("增加一条数据");
boolean result;
if (mapper.insertData()) result = true;
else result = false;
System.out.println(result);
}
// @Test
// void selectData(){
// System.out.println("查询id=10的name");
// System.out.println(mapper.selectAll());
// }
@Test
void selectData(){
System.out.println("查询id=10的name");
System.out.println(mapper.selectAll(10));
}
}
执行测试方法
查询id=10的name
2025-06-02 09:48:46.929 INFO 124 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2025-06-02 09:48:47.281 INFO 124 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
零基础学Java
9.数据库表
CREATE DATABASE db_video;
USE db_video;
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `t_video`
-- ----------------------------
DROP TABLE IF EXISTS `t_video`;
CREATE TABLE `t_video` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`author` varchar(20) DEFAULT NULL,
`video_view` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_video
-- ----------------------------
INSERT INTO `t_video` VALUES ('10', '零基础学Java', '张工程师', '100000');
INSERT INTO `t_video` VALUES ('20', '如何做鱼香肉丝', '李厨师', '80000');
INSERT INTO `t_video` VALUES ('30', '职场日常妆', '王女士', '76000');
INSERT INTO `t_video` VALUES ('40', '动作电影剪辑', '老赵', '66000');
四、引入Controller
mapper接口内容
package com.mr._20250602spring_mybatis.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import com.mr._20250602spring_mybatis.pojo.T_video;
public interface EmpMapper {
// @Select("select name from t_video where id = 10")
// boolean selectAll();
@Insert("insert into t_video values(33,'springboot','sun',22)")
boolean insertData();
@Select("select name from t_video where id = #{id}")
String selectAll(int id);
}
Controller类文件内容
package com.mr._20250602spring_mybatis.controller;
import com.mr._20250602spring_mybatis.mapper.EmpMapper;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/springboot")
public class a {
@Autowired
EmpMapper mapper;
@GetMapping("t_video")
String video(@RequestParam Integer id){
// return mapper.selectAll(10);
return mapper.selectAll(id);
}
}
浏览器访问测试
http://localhost:8080/springboot/t_video?id=10
零基础学Java
五、引入R类,返回数据库表所有数据
1、引入R类
package com.mr._20250602spring_mybatis.controller;
public class R { // 通用返回值类
private Boolean bool; // boolean型对象
private Object obj; // 实体类对象
private String str; // 字符串信息
// 为通用返回值类添加无参构造方法和有参构造方法
public R() {
}
public R(Boolean flag) {
this.bool = flag;
}
public R(Boolean flag, Object data) {
this.bool = flag;
this.obj = data;
}
public R(Boolean flag, String msg) {
this.bool = flag;
this.str = msg;
}
public R(String msg) {
this.str = msg;
}
// 分别为上述的3个属性添加Getter/Setter方法
public Boolean getFlag() {
return bool;
}
public void setFlag(Boolean flag) {
this.bool = flag;
}
public Object getData() {
return obj;
}
public void setData(Object data) {
this.obj = data;
}
public String getMsg() {
return str;
}
public void setMsg(String msg) {
this.str = msg;
}
}
2、mapper接口增加select * from t_video
package com.mr._20250602spring_mybatis.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import com.mr._20250602spring_mybatis.pojo.T_video;
import java.util.List;
public interface EmpMapper {
// @Select("select name from t_video where id = 10")
// boolean selectAll();
@Insert("insert into t_video values(33,'springboot','sun',22)")
boolean insertData();
@Select("select name from t_video where id = #{id}")
String selectAll(int id);
@Select("select * from t_video")
List<T_video> selectall();
}
3、Controller类增加映射路径all
package com.mr._20250602spring_mybatis.controller;
import com.mr._20250602spring_mybatis.mapper.EmpMapper;
import com.mr._20250602spring_mybatis.pojo.T_video;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/springboot")
public class a {
@Autowired
EmpMapper mapper;
@GetMapping("t_video")
String video(@RequestParam Integer id){
// return mapper.selectAll(10);
return mapper.selectAll(id);
}
@GetMapping("all")
public R selectVideo(){
return new R(true, mapper.selectall());
}
}
4、启动项目,访问测试
六、遇到的问题
- 1、依赖版本问题
这里采用的是书本自带的案例库进行了比对,版本对不上的复制了书本案例的版本,比如下面这个是我在IDEA创建项目时生成的spring-boot-starter-parent版本3.5.0,但是有了接口文件后启动项目时候报错了
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
替换成2.5.4版本后启动成功
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.4</version> <relativePath /> <!-- lookup parent from repository --> </parent>
2、SQL语句问题
mapper接口中使用注解方式写sql语句时,字符串值用单引号,避免和注解的整体sql语句的双引号冲突。这里如果写错,启动程序时也会提示sql语句某个位置有异常。比如
@Insert("insert into t_video values(33,'springboot','sun',22)")
boolean insertData();
- 3、步骤前后顺序问题
比如,引用了Mybatis依赖,application配置文件就得有数据库连接信息,不然启动报错
大佬们,小试牛刀,见笑了。更多精彩内容,敬请期待!