当前位置:首页 > 编程笔记 > 正文
已解决

Spring Boot 整合 MyBatis Plus

来自网友在路上 159859提问 提问时间:2023-11-05 21:48:00阅读次数: 59

最佳答案 问答题库598位专家为你答疑解惑

目录

一、初始化演示数据

二、创建应用

二、应用配置

三、实体类

四、Mapper

五、Mapper 映射文件

六、Service

七、Service 层抽象接口

八、配置 Mapper 扫描包

九、在日志中输出 SQL

十、测试


MyBatis Plus 是 MyBatis 框架的一个增强。除了基本的 MyBatis 功能外,它还提供了快速的 CURD 方法,以及投影查询、分页查询、动态条件等等功能,极大的提高了开发效率。

本文将会通过案例教你如何在 Spring Boot 中整合 MyBatis Plus。

文中使用的软件版本如下:

  • Spring Boot:3.0.3
  • MySQL:8.0.0
  • MyBatis Plus:3.5.4

一、初始化演示数据

首先在本地数据库执行以下 SQL 脚本,创建一张名为 t_user 的数据表:

CREATE TABLE `t_user` (`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`enabled` tinyint unsigned NOT NULL COMMENT '是否启用。0:禁用,1:启用',`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '名字',PRIMARY KEY (`id`),UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户';

然后再执行如下脚本,创建初始记录:

INSERT INTO `demo`.`t_user` (`id`, `create_at`, `enabled`, `name`) VALUES (3, '2023-10-31 15:11:34', 1, '刘备');
INSERT INTO `demo`.`t_user` (`id`, `create_at`, `enabled`, `name`) VALUES (4, '2023-10-31 15:11:34', 1, '关羽');
INSERT INTO `demo`.`t_user` (`id`, `create_at`, `enabled`, `name`) VALUES (5, '2023-10-31 15:11:34', 1, '张飞');

二、创建应用

通过 Spring Initializer 快速初始化一个 Spring Boot 工程。添加 mybatis-plus-boot-starter 以及 mysql-connector-j (MySQL 驱动)依赖。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version>
</dependency>
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>

二、应用配置

在 application.yaml 中配置必要的基础配置信息:

spring:# 基本的数据源配置datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=trueusername: rootpassword: root# MyBatis Plus 的配置
mybatis-plus:# mybatis 配置文件的路径# config-location: "classpath:mybatis/mybatis.config"# mapper 映射文件的路径,可以有多个 mapper-locations:- "classpath*:mappers/**/*.xml"

除了必须的数据源配置外,还定义了 MyBatis Plus 的配置。

  • config-location:指定了 MyBatis 配置文件的路径(非必须的)。
  • mapper-locations:指定要加载 mapper 文件,支持使用通配符。本例中的配置表示加载 classpath 下 mappers 目录以及其所有子目录下所有以 xml 结尾的文件。该配置是一个数组,可以配置多个加载路径。

更多关于 MyBatis Plus 的可用配置,可以参考其 官方文档。

三、实体类

创建一个实体类 User,对应上面的 t_user 表:

package cn.springdoc.demo.entity;import java.time.LocalDateTime;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;@TableName("t_user")
public class User {@TableId(type = IdType.AUTO)private Long id;@TableFieldprivate String name;@TableFieldprivate Boolean enabled;@TableFieldprivate LocalDateTime createAt;// 省略 get/set/toString 等方法
}

@TableName 注解是必须的,用于指定数据库中的表名称。 @TableId 注解也是必须的,用户指定表的 ID 字段,并且通过 type 属性设置了 ID 值为 “数据库自增”。

使用 @TableField 注解来定义与数据表中对应的列。注意,表中的列名使用的是下划线,而实体类中字段名称使用的是驼峰。 框架会自动完成这个转换,你不用担心。

如果你的表列名和实体属性名称之间不能自动完成这种转换,需要通过该注解的 value 属性来定义列名,如:@TableField("u_nick_name")。

@TableField 注解还有一个重要的 boolean 属性:exist,用于定义那些在实体中的 “非 DB 列” 字段。

例如:需要在实体中添加一个额外的 nickName 字段,用于封装检索的结果,这个字段并在表中并没有对应的数据列,此时就需要设置 exist 属性为 false。

@TableField(exist = false)
private String nickName;

否则在运行时你可能会遇到 “Unknown column” 异常:

org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'nick_name' in 'field list'
### The error may exist in cn/springdoc/demo/mapper/UserMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT  id,name,enabled,create_at,nick_name  FROM t_user
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'nick_name' in 'field list'
; bad SQL grammar []

更多可用的注解,可以参阅 官方文档。

四、Mapper

创建 UserMapper 接口,继承 BaseMapper,并且通过泛型指定实体类类型:

package cn.springdoc.demo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.springdoc.demo.entity.User;public interface UserMapper extends BaseMapper<User>{/*** 根据 name 检索一条记录* @param name* @return*/User getByName (String name);
}

BaseMapper 已经预置了很多 CRUD 的方法,可以直接使用。

并且,还在这个接口中定义了一个自定义方法 getByName(),根据 name 检索一条记录。添加这个方法的目的是测试 Mapper 映射文件是否成功加载。

五、Mapper 映射文件

在 src/main/resources/mappers 目录下创建 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="cn.springdoc.demo.mapper.UserMapper"><select id="getByName" resultType="cn.springdoc.demo.entity.User">SELECT * FROM `t_user` WHERE `name` = #{name}</select></mapper>

在 UserMapper.xml 中,通过 select 节点实现了 UserMapper 接口中的 getByName 方法。

六、Service

MyBatis Plus 甚至还提供了一个 ServiceImpl<M extends BaseMapper<T>, T> 抽象类,它也预定义了很多 CRUD 的方法。

我们的 Service 类可以直接继承它,指定泛型为实体类的 Mapper 接口以及实体类类型。

package cn.springdoc.demo.service;import org.springframework.stereotype.Service;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import cn.springdoc.demo.entity.User;
import cn.springdoc.demo.mapper.UserMapper;@Service
public class UserService extends ServiceImpl<UserMapper, User>{}

七、Service 层抽象接口

如果你喜欢抽象出 Service 接口的话,MyBatis Plus 也提供了一个接口:IService<T> 可用于继承。

定义业务接口,继承 IService:

import com.baomidou.mybatisplus.extension.service.IService;
import cn.springdoc.demo.entity.User;
// UserService 继承 IService 接口
public interface UserService  extends IService<User>{
}

业务接口实现类 UserServiceImpl,实现业务接口并且继承 ServiceImpl 抽象类:

package cn.springdoc.demo.service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.springdoc.demo.entity.User;
import cn.springdoc.demo.mapper.UserMapper;// UserServiceImpl 实现类,实现 UserService 接口,并且继承 ServiceImpl 抽象类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

我个人觉得除非实在是有必要,不然真的没必要在 Service 抽象出接口。写一辈子代码,也遇不到几次 Service 多实现的场景。

八、配置 Mapper 扫描包

在 main 类上添加 @MapperScan 注解,指定 mapper 接口所在的包:

package cn.springdoc.demo;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("cn.springdoc.demo.mapper") // mapper 接口所在的包
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

九、在日志中输出 SQL

为了看到执行的 SQL 日志,可以在 application.yaml 把 mapper 所在包的日志级别设置为 DEBUG:

logging:level:cn.springdoc.demo.mapper: DEBUG

至此,整合就完成了。

十、测试

创建测试类:

package cn.springdoc.demo.test;import java.util.List;import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;import cn.springdoc.demo.entity.User;
import cn.springdoc.demo.mapper.UserMapper;
import cn.springdoc.demo.service.UserService;@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {static final Logger log = LoggerFactory.getLogger(DemoApplicationTests.class);@AutowiredUserService userService;@Testpublic void test() throws Exception {// 检索所有记录List<User> users = this.userService.list();users.stream().forEach(user -> {log.info("user = {}", user);});// 从 Service 中获取到注入的 Mapper,强制转换为具体的实体 MapperUserMapper userMapper = (UserMapper) this.userService.getBaseMapper();// 调用 Mapper 中的方法User user = userMapper.getByName("刘备");log.info("user = {}", user);}
}

在测试类中注入了 UserService,执行了 2 个查询。

首先,使用 MyBatis Plus 提供的 list() 方法检索出表中的所有记录。

然后,再通过 getBaseMapper() 方法获取到 Service 中注入的 BaseMapper 接口,并且强制转换为对应的 UserMapper。然后调用我们在接口中自定义的方法。

执行测试,输出日志如下:

[           main] c.s.demo.mapper.UserMapper.selectList    : ==>  Preparing: SELECT id,name,enabled,create_at FROM t_user
[           main] c.s.demo.mapper.UserMapper.selectList    : ==> Parameters: 
[           main] c.s.demo.mapper.UserMapper.selectList    : <==      Total: 3
[           main] c.s.demo.test.DemoApplicationTests       : user = User [id=3, name=刘备, enabled=true, createAt=2023-10-31T15:11:34]
[           main] c.s.demo.test.DemoApplicationTests       : user = User [id=4, name=关羽, enabled=true, createAt=2023-10-31T15:11:34]
[           main] c.s.demo.test.DemoApplicationTests       : user = User [id=5, name=张飞, enabled=true, createAt=2023-10-31T15:11:34]
[           main] c.s.demo.mapper.UserMapper.getByName     : ==>  Preparing: SELECT * FROM `t_user` WHERE `name` = ?
[           main] c.s.demo.mapper.UserMapper.getByName     : ==> Parameters: 刘备(String)
[           main] c.s.demo.mapper.UserMapper.getByName     : <==      Total: 1
[           main] c.s.demo.test.DemoApplicationTests       : user = User [id=3, name=刘备, enabled=true, createAt=2023-10-31T15:11:34]

如你所见,一切OK!

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"Spring Boot 整合 MyBatis Plus":http://eshow365.cn/6-33033-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!