SpringBoot 2.3 集成 Mybatis Plus 3.4

Java 专栏收录该内容
100 篇文章 0 订阅




1 摘要

众所周知,Mybatis 是一个优秀的数据持久层框架,有着广泛的应用,其半自动化的特性既是优点也是缺点,优点是性能高,缺点是数据库语句依然需要开发者自行编写,对于一些基础的CRUD操作,将消耗开发者的大量时间和精力。为了减少开发者重复编写基本增删改查(CRUD)操作,国内的技术团队开发并开源了 Mybatis Plus 框架,从此,程序员将更加专注于业务开发,对于简单的增删改查将不需要再手写SQL。Mybatis Plus 是基于 Mybatis 开发,对其做了增强,其根本核心依旧是 Mybatis,Mybatis 的特性也全部支持。本文将介绍基于 SpringBoot 2.3 集成 Mybatis Plus 3.4。

Mybatis Plus 官方文档: https://baomidou.com/guide

2 核心依赖

./demo-mybatis-plus/pom.xml
        <!-- Mybatis Plus(include Mybatis) -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

其中 ${mybatis-plus.version} 的版本号为 3.4.0

完整依赖参考 pom.xml 文件

注意事项 : 引入 Mybatis Plus 之后就不需要再引入 Mybatis 的依赖,Mybatis Plus 中已经集成 Mybaits,重复依赖可能导致版本冲突的问题

3 配置信息

3.1 application.yml 配置文件

./demo-mybatis-plus/src/main/resources/application.yml
## config

## server
server:
  port: 8450

## spring config
spring:
  datasource:
    url: "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8\
      &useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
      &useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true\
      &nullCatalogMeansCurrent=true"
    username: root
    password: "root"
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver

## mybatis-plus
mybatis-plus:
  mapper-locations: classpath*:mybatis/*.xml
  type-aliases-package: com.ljq.dmeo.springboot.mybatisplus.model.entity

## mybatis log
logging:
  level:
    com.ljq.demo.springboot.mybatisplus.dao: debug

注意事项 : 在引入 mybatis-plus-boot-starter 依赖之后,需要使用 Mybatis Plus 对应的配置来取代旧有的 Mybatis 配置,两者的区别仅在于开头的配置(要以 mybatis-plus 开头),如果使用旧有的 Mybatis 配置,将不会生效,从而引起项目运行异常,如无法扫描到对应的 mapper 文件。

3.2 分页配置

Mybatis Plus 自带分页查询工具,但是需要手动配置

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/common/config/MybatisPlusConfig.java
package com.ljq.demo.springboot.mybatisplus.common.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: MybatisPlus 配置信息
 * @Author: junqiang.lu
 * @Date: 2020/9/1
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循 mybatis 的规则
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

}

注意事项: 从 Mybatis Plus 3.4 开始,将使用新的分页配置,原来的分页配置类 PaginationInterceptor 已经被弃用

更多配置参考 Mybatis Plus 官方文档: https://baomidou.com/guide/interceptor.html

4 演示数据库表

./doc/sql/demo-database-create.sql
/*==============================================================*/
/* DBMS name:      MySQL 5.0                                    */
/* Created on:     2018/9/29 16:10:13                           */
/*==============================================================*/


drop database if exists `demo`;
create database `demo` default character set utf8mb4 collate utf8mb4_general_ci;
use `demo`;

drop table if exists user;

/*==============================================================*/
/* Table: user                                                  */
/*==============================================================*/
create table user
(
   id                   bigint unsigned not null auto_increment comment 'id 主键',
   user_name            varchar(30) comment '用户名',
   user_passcode        varchar(100) comment '登陆密码',
   user_email           varchar(50) comment '邮箱',
   user_insert_time     varchar(30) comment '用户注册时间',
   user_update_time     varchar(30) comment '用户更新时间',
   user_status          tinyint default 1 comment '用户账号状态,1正常(默认),2禁止登陆',
   user_version         int unsigned default 1 comment '版本控制字段(默认1)',
   user_del             tinyint default 0 comment '逻辑删除字段,0正常(默认),1删除',
   primary key (id)
)
ENGINE = INNODB DEFAULT
CHARSET = UTF8MB4;

alter table user comment '用户表';

初始化测试数据

./doc/sql/demo-database-test.sql
## test-demo  

-- 添加测试用户  
INSERT INTO `user`(`user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`)
  VALUES('tom', MD5('demo12345'), 'tom@example.com', NOW(), NOW()),
        ('bob', MD5('demo12345'), 'bob@example.com', NOW(), NOW()),
        ('jack', MD5('demo12345'), 'jack@example.com', NOW(), NOW()),
        ('lily', MD5('demo12345'), 'lily@example.com', NOW(), NOW()),
        ('liming', MD5('demo12345'), 'liming@example.com', NOW(), NOW());

5 核心代码

5.1 实体类

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/entity/UserEntity.java
package com.ljq.demo.springboot.mybatisplus.model.entity;

import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

/**
 * 用户表实体类
 *
 * @author junqiang.lu
 * @date 2020-09-01 13:24:08
 */
@Data
@TableName(value = "user", resultMap = "userMap")
@ApiModel(value = "用户表", description = "用户表")
public class UserEntity implements Serializable {

	private static final long serialVersionUID = 1L;

     /**
      * id 主键
      **/
    @TableId(value = "id", type = IdType.AUTO)
    @ApiModelProperty(value = "id 主键", name = "id")
    private Long id;
    /**
     * 用户名
     **/
    @TableField(value = "user_name")
    @ApiModelProperty(value = "用户名", name = "userName")
    private String userName;
    /**
     * 登陆密码
     **/
    @TableField(value = "user_passcode")
    @ApiModelProperty(value = "登陆密码", name = "userPasscode")
    private String userPasscode;
    /**
     * 邮箱
     **/
    @TableField(value = "user_email")
    @ApiModelProperty(value = "邮箱", name = "userEmail")
    private String userEmail;
    /**
     * 用户注册时间
     **/
    @TableField(value = "user_insert_time")
    @ApiModelProperty(value = "用户注册时间", name = "userInsertTime")
    private String userInsertTime;
    /**
     * 用户更新时间
     **/
    @TableField(value = "user_update_time")
    @ApiModelProperty(value = "用户更新时间", name = "userUpdateTime")
    private String userUpdateTime;
    /**
     * 用户账号状态,1正常(默认),2禁止登陆
     **/
    @TableField(value = "user_status")
    @ApiModelProperty(value = "用户账号状态,1正常(默认),2禁止登陆", name = "userStatus")
    private Integer userStatus;
    /**
     * 版本控制字段(默认1)
     **/
    @TableField(value = "user_version")
    @ApiModelProperty(value = "版本控制字段(默认1)", name = "userVersion")
    private Integer userVersion;
    /**
     * 逻辑删除字段,0正常(默认),1删除
     **/
    @TableLogic(value = "0", delval = "1")
    @TableField(value = "user_del")
    @ApiModelProperty(value = "逻辑删除字段,0正常(默认),1删除", name = "userDel")
    private Integer userDel;


}

这里使用到的Mybatis Plus 注解有:

@TableName: 用于指定实体类对应的数据库表

@TableId : 用在主键对应的属性上,可以指定主键对应的数据库字段名,同时可以指定主键的生成策略(默认使用雪花算法生成一个 Long 类型数字)

@TableField : 用在非主键对应的属性上,可以指定属性对应的数据库字段名,同时也可以设置字段是否为空等属性

@TableLogic : 用在标记逻辑删除的字段属性上,使用该注解后,Myabtis Plus 所有针对该表的删除都将执行逻辑删除(即更新操作),而不使用该注解,Mybatis Plus 执行的删除操作为物理删除

更多的注解参考 Mybatis Plus 官方文档: https://baomidou.com/guide/annotation.html

5.2 DAO 层

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/dao/UserDao.java
package com.ljq.demo.springboot.mybatisplus.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ljq.demo.springboot.mybatisplus.model.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

/**
 * 用户表
 * 
 * @author junqiang.lu
 * @date 2020-08-31 14:09:53
 */
@Mapper
@Component("userDao")
public interface UserDao extends BaseMapper<UserEntity> {
	
}

开发者手写的 DAO 接口需要继承 Mybatis Plus 提供的 com.baomidou.mybatisplus.core.mapper.BaseMapper 接口,同时指定泛型

5.3 请求参数类

增删改查接口对应的请求参数封装类

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/param/UserSaveParam.java
./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/param/UserInfoParam.java
./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/param/UserListParam.java
./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/param/UserUpdateParam.java
./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/model/param/UserDeleteParam.java

完整代码参考项目 Github 源码: https://github.com/Flying9001/springBootDemo

5.4 Service 层

Service 接口

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/service/UserService.java
package com.ljq.demo.springboot.mybatisplus.service;

import com.ljq.demo.springboot.mybatisplus.common.api.ApiResult;
import com.ljq.demo.springboot.mybatisplus.model.param.*;

/**
 * 用户表业务层接口
 * 
 * @author junqiang.lu
 * @date 2020-08-31 14:09:53
 */
public interface UserService {

	/**
     * 保存(单条)
     *
     * @param userSaveParam
     * @return
     * @throws Exception
     */
	ApiResult save(UserSaveParam userSaveParam) throws Exception;

	/**
     * 查询详情(单条)
     *
     * @param userInfoParam
     * @return
     * @throws Exception
     */
	ApiResult info(UserInfoParam userInfoParam) throws Exception;

	/**
     * 查询列表
     *
     * @param userListParam
     * @return
     * @throws Exception
     */
	ApiResult list(UserListParam userListParam) throws Exception;

	/**
     * 更新(单条)
     *
     * @param userUpdateParam
     * @return
     * @throws Exception
     */
	ApiResult update(UserUpdateParam userUpdateParam) throws Exception;

	/**
     * 删除(单条)
     *
     * @param userDeleteParam
     * @return
     * @throws Exception
     */
	ApiResult delete(UserDeleteParam userDeleteParam) throws Exception;

}

Service 实现类

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/service/impl/UserServiceImpl.java
package com.ljq.demo.springboot.mybatisplus.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljq.demo.springboot.mybatisplus.common.api.ApiResult;
import com.ljq.demo.springboot.mybatisplus.dao.UserDao;
import com.ljq.demo.springboot.mybatisplus.model.entity.UserEntity;
import com.ljq.demo.springboot.mybatisplus.model.param.*;
import com.ljq.demo.springboot.mybatisplus.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
 * 用户表业务层具体实现类
 *
 * @author junqiang.lu
 * @date 2020-08-31 14:09:53
 */
@Service("userService")
@Transactional(rollbackFor = {Exception.class})
@Slf4j
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;

	/**
	 * 保存(单条)
	 *
	 * @param userSaveParam
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
	public ApiResult save(UserSaveParam userSaveParam) throws Exception {
		// 请求参数获取
		UserEntity userParam = new UserEntity();
		BeanUtil.copyProperties(userSaveParam,userParam,CopyOptions.create()
				.setIgnoreNullValue(true).setIgnoreError(true));
		// 保存
		String nowTime = String.valueOf(System.currentTimeMillis());
		userParam.setUserInsertTime(nowTime);
		userParam.setUserUpdateTime(nowTime);
		userDao.insert(userParam);

		return ApiResult.success(userParam.getId());
	}

	/**
	 * 查询详情(单条)
	 *
	 * @param userInfoParam
	 * @return
	 * @throws Exception
	 */
	@Override
	public ApiResult info(UserInfoParam userInfoParam) throws Exception {
		UserEntity userDB = userDao.selectById(userInfoParam.getId());
		return ApiResult.success(userDB);
	}

	/**
	 * 查询列表
	 *
	 * @param userListParam
	 * @return
	 * @throws Exception
	 */
	@Override
	public ApiResult list(UserListParam userListParam) throws Exception {
		LambdaQueryWrapper<UserEntity> userWrapper = new LambdaQueryWrapper<>();
		userWrapper.like(Objects.nonNull(userListParam.getUserName()), UserEntity::getUserName,
				userListParam.getUserName());
		IPage<UserEntity> page = new Page<>(userListParam.getCurrentPage(),userListParam.getPageSize());
		userWrapper.orderBy(true, userListParam.isAscFlag(), UserEntity::getId);
		page = userDao.selectPage(page, userWrapper);

		return ApiResult.success(page);
	}

	/**
	 * 更新(单条)
	 *
	 * @param userUpdateParam
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
	public ApiResult update(UserUpdateParam userUpdateParam) throws Exception {
		LambdaQueryWrapper<UserEntity> userWrapper = new LambdaQueryWrapper<>();
		userWrapper.eq(true, UserEntity::getId, userUpdateParam.getId());
		int countUser = userDao.selectCount(userWrapper);
		if (countUser < 1) {
			return ApiResult.failure("用户不存在");
		}
		// 请求参数获取
		UserEntity userParam = new UserEntity();
		BeanUtil.copyProperties(userUpdateParam, userParam, CopyOptions.create().ignoreNullValue().ignoreError());
		userParam.setUserUpdateTime(String.valueOf(System.currentTimeMillis()));
		userDao.updateById(userParam);

		return ApiResult.success();
	}

	/**
	 * 删除(单条)
	 *
	 * @param userDeleteParam
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
	public ApiResult delete(UserDeleteParam userDeleteParam) throws Exception {
		int countUser = userDao.deleteById(userDeleteParam.getId());
		if (countUser < 1) {
			return ApiResult.failure("用户不存在");
		}
		return ApiResult.success();
	}	
}

基础的增删改查在这里都有对应的示例,包括根据条件分页查询

5.5 Controller 层

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/controller/UserController.java
package com.ljq.demo.springboot.mybatisplus.controller;

import com.ljq.demo.springboot.mybatisplus.common.api.ApiResult;
import com.ljq.demo.springboot.mybatisplus.model.param.*;
import com.ljq.demo.springboot.mybatisplus.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * 用户表
 * 
 * @author junqiang.lu
 * @date 2020-08-31 16:39:56
 */
@Slf4j
@RestController
@RequestMapping(value = "/api/mybatis/plus/user")
@Api(value = "用户表控制层", tags = "用户表控制层")
public class UserController {

	@Autowired
	private UserService userService;

    /**
     * 保存(单条)
     *
     * @param userSaveParam
     * @return
     */
    @PostMapping(value = "/add", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "用户表保存(单条)",  notes = "用户表保存(单条)")
    public ResponseEntity<?> save(@RequestBody UserSaveParam userSaveParam) throws Exception{
        ApiResult apiResult = userService.save(userSaveParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(apiResult, headers, HttpStatus.OK);
    }

    /**
     * 查询详情(单条)
     *
     * @param userInfoParam
     * @return
     */
    @GetMapping(value = "/info", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "用户表查询详情(单条)",  notes = "用户表查询详情(单条)")
    public ResponseEntity<?> info(UserInfoParam userInfoParam) throws Exception {
        ApiResult apiResult = userService.info(userInfoParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(apiResult, headers, HttpStatus.OK);
    }

    /**
     * 查询列表
     *
     * @param userListParam
     * @return
     */
    @GetMapping(value = "/list", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "用户表查询列表",  notes = "用户表查询列表")
    public ResponseEntity<?> list(UserListParam userListParam) throws Exception {
        ApiResult apiResult = userService.list(userListParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(apiResult, headers, HttpStatus.OK);
    }

    /**
     * 修改(单条)
     *
     * @param userUpdateParam
     * @return
     */
    @PutMapping(value = "/update", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "用户表修改(单条)",  notes = "用户表修改(单条)")
    public ResponseEntity<?> update(@RequestBody UserUpdateParam userUpdateParam) throws Exception {
        ApiResult apiResult = userService.update(userUpdateParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(apiResult, headers, HttpStatus.OK);
    }

    /**
     * 删除(单条)
     *
     * @param userDeleteParam
     * @return
     */
    @DeleteMapping(value = "/delete", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "用户表删除(单条)",  notes = "用户表删除(单条)")
    public ResponseEntity<?> delete(@RequestBody UserDeleteParam userDeleteParam) throws Exception {
        ApiResult apiResult = userService.delete(userDeleteParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(apiResult, headers, HttpStatus.OK);
    }

}

5.6 SpringBoot 启动类

./demo-mybatis-plus/src/main/java/com/ljq/demo/springboot/mybatisplus/DemoMybatisPlusApplication.java
package com.ljq.demo.springboot.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author junqiang.lu
 */
@EnableSwagger2
@SpringBootApplication(scanBasePackages = {"com.ljq.demo.springboot.mybatisplus.*"})
@MapperScan(basePackages = {"com.ljq.demo.springboot.mybatisplus.dao"})
public class DemoMybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoMybatisPlusApplication.class, args);
    }

}

注意事项: 需要使用 @MapperScan 指定扫描 mapper 所在的包,即 DAO 层

5.7 Mybatis mapper 文件

使用 Mybatis Plus 之后,依旧可以使用 mapper 文件,尽管一些基本的增删改查不需要再手写 SQL了,但是作者还是建议保留 mapper 文件,对于一些复杂的查询,手写 SQL 可能更加简洁

./demo-mybatis-plus/src/main/resources/mybatis/UserDao.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.ljq.demo.springboot.mybatisplus.dao.UserDao">

	<!-- 用户表结果集resultMap -->
    <resultMap type="com.ljq.demo.springboot.mybatisplus.model.entity.UserEntity" id="userMap">
        <result property="id" column="id"/>
        <result property="userName" column="user_name"/>
        <result property="userPasscode" column="user_passcode"/>
        <result property="userEmail" column="user_email"/>
        <result property="userInsertTime" column="user_insert_time"/>
        <result property="userUpdateTime" column="user_update_time"/>
        <result property="userStatus" column="user_status"/>
        <result property="userVersion" column="user_version"/>
        <result property="userDel" column="user_del"/>
    </resultMap>

   <!-- 用户表-基础字段 -->
	<sql id="user_base_field">
        `id`,
        `user_name`,
        `user_passcode`,
        `user_email`,
        `user_insert_time`,
        `user_update_time`,
        `user_status`,
        `user_version`,
        `user_del`
	</sql>

</mapper>

Mybatis Plus 同样可以指定 mapper 文件中定义的 resultMap ,具体使用到的注解为实体类上 @TableName

5.8 Swagger 接口文档

启动项目,打开浏览器,输入地址:

http://127.0.0.1:8450/swagger-ui.html

即可进行接口测试

至此基于 SpringBoot 2.x 集成 Mybatis Plus 3.4 已经完成

6 推荐学习方法

6.1 学习方法

有问题,先搜索,然后查阅官方文档,找到对应的说明

6.2 实践操作步骤

  • 1 按照官方文档启动项目
  • 2 实现基本的增删改查
  • 3 实现一些高级功能,如指定 resultMap,逻辑删除等等

7 推荐参考资料

MybatisPlus 官方文档

MybatisPlus–3.5 指定查询列

MyBatis-Plus 用起来真的很舒服

mybatis-plus配置找不到Mapper接口路径的坑

MyBatis-Plus 分页查询以及自定义sql分页

8 Github 源码

Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo

个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
404Code

  • 0
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值