Bootstrap

不写SQL一行代码实现多表联查与数据封装【MyBatis-Plus-Join的基本使用】

初始准备

1.开发语言:java——》jdk8

2.开发工具:idea——》IntelliJ IDEA 2022.3(其他版本不影响)

3.其他配置:数据库:Mysql5.7,Maven3.6.3,

4.使用技术:spring-boot、Mybatis-Plus、MyBatis-Plus-Join、swagger、lombok(文章末尾pom文件有具体版本信息)

业务背景:在不写SQL的情况下实现多表连查与数据封装,避免多次修改mapper.xml文件中的字段,在有字段添加或删除时只需在实体类中添加与删除即可,一行代码实现数据查询与封装,后续业务变更只需修改一处代码即可。

注意事项:注意MyBatis-Plus-Join的版本与MyBatis-Plus的版本对应关系,详细对应关系请查询MyBatis-Plus-Join版本对应关系

数据关系:

解决问题:如果我们需要查询某个用户下的资源信息至少需要连六张表才能查询出来,使用mybatis-plus-join后只需一行代码即可。

gitee地址【mybatis-plus-join: 一个使用mybatis-plus-join框架的demo

效果:

  1. 一对一连查【查询一个用户信息以及查询用户详细信息并封装】

    1. 代码实现
          @Override
          public SysUser queryDetailsV1(String id) {
              if (StrUtil.isBlank(id)) return new SysUser();
              return this.selectJoinOne(
                      SysUser.class,
                      new MPJLambdaWrapper<SysUser>()
                              .selectAll(SysUser.class)
                              .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                              .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                              .eq(SysUser::getId, id)
              );
          }

    2. 效果展示
    3. sql预览
      select u.*, sud.*
      from sys_user u
               left join sys_user_detail sud on u.id = sud.user_id;

  2. 一对多连查【查询一个用户下的所有角色、权限、资源信息并封装数据】

    1. 代码实现
          @Override
          public SysUser queryDetailsV2(String id) {
              if (StrUtil.isBlank(id)) return new SysUser();
              else return this.selectJoinOne(
                      SysUser.class,
                      new MPJLambdaWrapper<SysUser>()
                              .selectAll(SysUser.class)
                              .selectCollection(
                                      SysRole.class,
                                      SysUser::getRoleInfo,
                                      r -> r.collection(
                                              SysAuthority.class,
                                              SysRole::getAuthorityInfo,
                                              a -> a.collection(
                                                      SysResource.class, SysAuthority::getResourceInfo
                                              )
                                      )
                              )
                              .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                              .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                              .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                              .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                              .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                              .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                              .eq(SysUser::getId, id)
              );
          }

    2. 效果展示
    3. sql预览
      select u.*, sur.*, sr.*, sra.*, sa.*, sar.*, s.*
      from sys_user u
               left join sys_user_role sur on u.id = sur.user_id
               left join sys_role sr on sur.role_id = sr.id
               left join sys_role_authority sra on sr.id = sra.role_id
               left join sys_authority sa on sra.authority_id = sa.id
               left join sys_authority_resource sar on sa.id = sar.authority_id
               left join sys_resource s on sar.resource_id = s.id
      where u.id = 'c098af0730602f98835292463c33e6da';

  3. 多对多连查【查询多个用户的角色、权限、资源信息并封装数据,分页查询时不推荐使用】

    1. 代码实现
      
          @Override
          public IPage<SysUser> queryDetailsV3(Integer pageNum, Integer pageSize, String userName) {
              MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                      .selectAll(SysUser.class)
                      .selectCollection(
                              SysRole.class,
                              SysUser::getRoleInfo,
                              r -> r.collection(
                                      SysAuthority.class,
                                      SysRole::getAuthorityInfo,
                                      a -> a.collection(
                                              SysResource.class, SysAuthority::getResourceInfo
                                      )
                              )
                      )
                      .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                      .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                      .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                      .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                      .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                      .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
              if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
              return super.baseMapper.selectJoinPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
          }

    2. 效果展示
    3. 不推荐原因:通常查询都是分页查询,表中有一对多时使用分页查询出来的数据条数显然不对劲,查询20页数据,但只查询出一条原因是该mybatis处理分页为原sql加限制查询如
      select * from (
      原本查询数据的sql
      ) limit (pageNum-1)*pageSize , pageSize

      如果原本的sql又联表(列表一对多)又分页就会有这问题,解决这个问题建议先查询一次实现分页,再查询一次实现数据封装;

    4. sql预览:

      1. 查询总条数

        select count(1)
        from (select u.id as `u.i`, age as a, u.name as `u.n`, u.`describe` as "u.`d`", u.other as `u.o`
              from sys_user u
                       left join sys_user_role sur on u.id = sur.user_id
                       left join sys_role sr on sur.role_id = sr.id
                       left join sys_role_authority sra on sr.id = sra.role_id
                       left join sys_authority sa on sra.authority_id = sa.id
                       left join sys_authority_resource sar on sa.id = sar.authority_id
                       left join sys_resource s on sar.resource_id = s.id) t

      2. 查询数据,字段太多没写全

        select *
        from (select u.id as `u.i`, age as a, u.name as `u.n`, u.`describe` as "u.`d`", u.other as `u.o`
              from sys_user u
                       left join sys_user_role sur on u.id = sur.user_id
                       left join sys_role sr on sur.role_id = sr.id
                       left join sys_role_authority sra on sr.id = sra.role_id
                       left join sys_authority sa on sra.authority_id = sa.id
                       left join sys_authority_resource sar on sa.id = sar.authority_id
                       left join sys_resource s on sar.resource_id = s.id) t
        limit 0,20
  4. 同时一对一连查与一对多连查【查询一个用户的详细信息、角色、权限、资源信息并封装数据】

    1. 代码实现
      
          @Override
          public SysUser queryDetailsV4(String id) {
              if (StrUtil.isBlank(id)) return new SysUser();
              else return this.selectJoinOne(
                      SysUser.class,
                      new MPJLambdaWrapper<SysUser>()
                              .selectAll(SysUser.class)
                              .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                              .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                              .selectCollection(
                                      SysRole.class,
                                      SysUser::getRoleInfo,
                                      r -> r.collection(
                                              SysAuthority.class,
                                              SysRole::getAuthorityInfo,
                                              a -> a.collection(
                                                      SysResource.class, SysAuthority::getResourceInfo
                                              )
                                      )
                              )
                              .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                              .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                              .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                              .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                              .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                              .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                              .eq(SysUser::getId, id)
              );
          }

    2. 效果展示
    3. sql预览
      select *
      from sys_user u
               left join sys_user_role sur on u.id = sur.user_id
               left join sys_role sr on sur.role_id = sr.id
               left join sys_role_authority sra on sr.id = sra.role_id
               left join sys_authority sa on sra.authority_id = sa.id
               left join sys_authority_resource sar on sa.id = sar.authority_id
               left join sys_resource s on sar.resource_id = s.id
               left join sys_user_detail sud on u.id = sud.user_id
      where u.id = 'c098af0730602f98835292463c33e6da'

  5. 多对多连查的同时封装每一个具体对象的一对一、一对多数据【查询多个用户的详细信息、角色、权限、资源信息并封装数据,分页查询时不推荐使用】

    1. 代码实现
          @Override
          public IPage<SysUser> queryDetailsV5(Integer pageNum, Integer pageSize, String userName) {
              MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                      .selectAll(SysUser.class)
                      .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                      .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                      .selectCollection(
                              SysRole.class,
                              SysUser::getRoleInfo,
                              r -> r.collection(
                                      SysAuthority.class,
                                      SysRole::getAuthorityInfo,
                                      a -> a.collection(
                                              SysResource.class, SysAuthority::getResourceInfo
                                      )
                              )
                      )
                      .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                      .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                      .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                      .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                      .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                      .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
              if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
              return this.selectJoinListPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
          }

    2. 效果展示
    3. 不推荐原因:不推荐原因还是连表查询有一对多关系时分页不准确问题。

数据库表

CREATE TABLE `sys_authority` (
  `id` varchar(255) NOT NULL COMMENT '主键id',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `describe` varchar(255) DEFAULT NULL COMMENT '描述',
  `other` varchar(255) DEFAULT NULL COMMENT '其他',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权限表'

CREATE TABLE `sys_authority_resource` (
  `authority_id` varchar(255) DEFAULT NULL COMMENT '权限id',
  `resource_id` varchar(255) DEFAULT NULL COMMENT '资源id',
  KEY `sys_authority_resource_authority_id_index` (`authority_id`),
  KEY `sys_authority_resource_resource_id_index` (`resource_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权限资源关联表'

CREATE TABLE `sys_resource` (
  `id` varchar(255) NOT NULL COMMENT '主键id',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `url` text COMMENT '资源地址',
  `describe` text COMMENT '描述',
  `other` text COMMENT '其他',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='资源表'

CREATE TABLE `sys_role` (
  `id` varchar(255) NOT NULL COMMENT '主键id',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `describe` text COMMENT '描述',
  `other` text COMMENT '其他',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表'

CREATE TABLE `sys_role_authority` (
  `role_id` varchar(255) DEFAULT NULL COMMENT '角色id',
  `authority_id` varchar(255) DEFAULT NULL COMMENT '权限id',
  KEY `sys_role_authority_authority_id_index` (`authority_id`),
  KEY `sys_role_authority_role_id_index` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色权限中间表'

CREATE TABLE `sys_user` (
  `id` varchar(255) NOT NULL COMMENT '主键id',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `describe` text COMMENT '描述',
  `other` text COMMENT '其他',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表'

CREATE TABLE `sys_user_detail` (
  `id` varchar(255) NOT NULL COMMENT '主键id',
  `phone` varchar(50) DEFAULT NULL COMMENT '联系电话',
  `other_details` text COMMENT '其他详细信息',
  `describe` text COMMENT '描述',
  `other` varchar(255) DEFAULT NULL COMMENT '其他',
  `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户详情表'

CREATE TABLE `sys_user_role` (
  `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
  `role_id` varchar(255) DEFAULT NULL COMMENT '角色id',
  KEY `sys_user_role_role_id_index` (`role_id`),
  KEY `sys_user_role_user_id_index` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色中间表'

实体类,推荐使用mybatis-plus代码生成器生成下以下代码,手动敲有点浪费时间。

目录结构

实体类

//package com.wanger.model.connect;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 权限资源关联表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:25:46
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_authority_resource")
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("系统权限、资源关联表")
public class SysAuthorityResource {

    @TableField("authority_id")
    @ApiModelProperty("权限id")
    private String authorityId;

    @TableField("resource_id")
    @ApiModelProperty("资源id")
    private String resourceId;

}

//package com.wanger.model.connect;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 角色权限中间表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:25:06
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_role_authority")
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("系统角色、权限关联表")
public class SysRoleAuthority {

    @TableField("role_id")
    @ApiModelProperty("角色id")
    private String roleId;

    @TableField("authority_id")
    @ApiModelProperty("权限id")
    private String authorityId;

}


//package com.wanger.model.connect;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 用户角色中间表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:24:47
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_user_role")
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("系统用户、角色关联表")
public class SysUserRole {

    @TableField("user_id")
    @ApiModelProperty("用户id")
    private String userId;

    @TableField("role_id")
    @ApiModelProperty("角色id")
    private String roleId;

}

//package com.wanger.model.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.List;

/**
 * 权限表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:01:57
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_authority")
@ApiModel("系统权限")
public class SysAuthority {

    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    @ApiModelProperty("主键id")
    private String id;

    @TableField("name")
    @ApiModelProperty("名称")
    private String name;

    @TableField("`describe`")
    @ApiModelProperty("描述")
    private String describe;

    @TableField("other")
    @ApiModelProperty("其他")
    private String other;

    @TableField(exist = false)
    @ApiModelProperty("资源信息列表")
    private List<SysResource> resourceInfo = new ArrayList<>();

}


//package com.wanger.model.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * 资源表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:02:21
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_resource")
@ApiModel("系统资源")
public class SysResource {

    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    @ApiModelProperty("主键id")
    private String id;

    @TableField("name")
    @ApiModelProperty("名称")
    private String name;

    @TableField("url")
    @ApiModelProperty("资源地址")
    private String url;

    @TableField("`describe`")
    @ApiModelProperty("描述")
    private String describe;

    @TableField("other")
    @ApiModelProperty("其他")
    private String other;

}

//package com.wanger.model.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.List;

/**
 * 角色表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:01:06
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_role")
@ApiModel("系统角色")
public class SysRole {

    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    @ApiModelProperty("主键id")
    private String id;

    @TableField("name")
    @ApiModelProperty("名称")
    private String name;

    @TableField("`describe`")
    @ApiModelProperty("描述")
    private String describe;

    @TableField("other")
    @ApiModelProperty("其他")
    private String other;

    @TableField(exist = false)
    @ApiModelProperty("权限信息列表")
    private List<SysAuthority> authorityInfo = new ArrayList<>();

}

//package com.wanger.model.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.List;

/**
 * 资源表
 *
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 14:00:29
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_user")
@ApiModel("系统角色")
public class SysUser {

    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    @ApiModelProperty("主键id")
    private String id;

    @TableField("age")
    @ApiModelProperty("年龄")
    private Integer age;

    @TableField("name")
    @ApiModelProperty("姓名")
    private String name;

    @TableField("`describe`")
    @ApiModelProperty("描述")
    private String describe;

    @TableField("other")
    @ApiModelProperty("其他")
    private String other;

    @TableField(exist = false)
    @ApiModelProperty("角色信息列表")
    private List<SysRole> roleInfo = new ArrayList<>();

    @TableField(exist = false)
    @ApiModelProperty("详细详细")
    private SysUserDetail sysUserDetail;


}


//package com.wanger.model.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.List;

/**
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/15 22:43:49
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_user_detail")
@ApiModel("用户详情")
public class SysUserDetail {

    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    @ApiModelProperty("主键id")
    private String id;

    @TableField("user_id")
    @ApiModelProperty("用户id")
    private String userId;

    @TableField("phone")
    @ApiModelProperty("联系电话")
    private String phone;

    @TableField("other_details")
    @ApiModelProperty("其他详细信息")
    private String otherDetails;

    @TableField("`describe`")
    @ApiModelProperty("描述")
    private String describe;

    @TableField("other")
    @ApiModelProperty("其他")
    private String other;

}

mapper类,这里只展示了sysUserMapper类,其他类以此类推

package com.wanger.mapper;

import com.github.yulichang.base.MPJBaseMapper;
import com.wanger.model.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 16:24:03
 */
@Mapper
public interface SysUserMapper extends MPJBaseMapper<SysUser> {
}

service类

package com.wanger.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.base.service.MPJJoinService;
import com.wanger.model.entity.SysResource;
import com.wanger.model.entity.SysUser;

import java.util.List;

/**
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 16:25:17
 */
public interface SysUserService extends MPJJoinService<SysUser> {

    IPage<SysResource> deepPageTurning(Integer pageNum, Integer pageSize, String name, String url);

    boolean addData(List<SysUser> userList);

    SysUser queryDetailsV1(String id);

    SysUser queryDetailsV2(String id);

    IPage<SysUser> queryDetailsV3(Integer pageNum, Integer pageSize, String userName);

    List<SysUser> queryDetailsV3_1(List<String> userIds);    

    SysUser queryDetailsV4(String id);

    IPage<SysUser> queryDetailsV5(Integer pageNum, Integer pageSize, String userName);

}

实现类

package com.wanger.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.wanger.mapper.SysUserMapper;
import com.wanger.model.connect.SysAuthorityResource;
import com.wanger.model.connect.SysRoleAuthority;
import com.wanger.model.connect.SysUserRole;
import com.wanger.model.entity.*;
import com.wanger.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wanger
 * @version 1.0
 * @Description TOD O
 * @date 2023/1/5 16:26:02
 */
@Service
public class SysUserServiceImpl extends MPJBaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserDetailService sysUserDetailService;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysRoleAuthorityService sysRoleAuthorityService;

    @Resource
    private SysAuthorityService sysAuthorityService;

    @Resource
    private SysAuthorityResourceService sysAuthorityResourceService;

    @Resource
    private SysResourceService sysResourceService;

    @Override
    public IPage<SysResource> deepPageTurning(Integer pageNum, Integer pageSize, String name, String url) {
        MPJLambdaWrapper<SysResource> wrapper = new MPJLambdaWrapper<>();
        if (StrUtil.isNotBlank(name)) wrapper.like(SysResource::getName, name);
        if (StrUtil.isNotBlank(url)) wrapper.like(SysResource::getUrl, url);
        return sysResourceService.page(new Page<>(pageNum, pageSize), wrapper);
    }

    @Override
    @Transactional
    public boolean addData(List<SysUser> userList) {
        if (CollUtil.isNotEmpty(userList)) {
            if (this.saveBatch(userList)) {
                List<SysRole> roleList = new ArrayList<>();
                List<SysAuthority> authorityList = new ArrayList<>();
                List<SysResource> resourceList = new ArrayList<>();
                userList.forEach(u -> {
                    List<SysRole> roleInfo = u.getRoleInfo();
                    if (CollUtil.isNotEmpty(roleInfo)) {
                        roleList.addAll(roleInfo);
                        roleInfo.forEach(r -> {
                            List<SysAuthority> authorityInfo = r.getAuthorityInfo();
                            if (CollUtil.isNotEmpty(authorityInfo)) {
                                authorityList.addAll(authorityInfo);
                                authorityInfo.forEach(a -> {
                                    List<SysResource> resourceInfo = a.getResourceInfo();
                                    if (CollUtil.isNotEmpty(resourceInfo)) {
                                        resourceList.addAll(resourceInfo);
                                    }
                                });
                            }
                        });
                    }
                });
                if (CollUtil.isNotEmpty(roleList)) sysRoleService.saveBatch(roleList);
                if (CollUtil.isNotEmpty(authorityList)) sysAuthorityService.saveBatch(authorityList);
                if (CollUtil.isNotEmpty(resourceList)) sysResourceService.saveBatch(resourceList);
                List<SysUserRole> userRoles = new ArrayList<>();
                List<SysRoleAuthority> roleAuthority = new ArrayList<>();
                List<SysAuthorityResource> authorityResource = new ArrayList<>();
                List<SysUserDetail> sysUserDetails = new ArrayList<>();
                userList.forEach(u -> {
                    List<SysRole> roleInfo = u.getRoleInfo();
                    sysUserDetails.add(u.getSysUserDetail());
                    if (CollUtil.isNotEmpty(roleInfo)) {
                        roleInfo.forEach(r -> {
                            userRoles.add(new SysUserRole(u.getId(), r.getId()));
                            List<SysAuthority> authorityInfo = r.getAuthorityInfo();
                            if (CollUtil.isNotEmpty(authorityInfo)) {
                                authorityInfo.forEach(a -> {
                                    roleAuthority.add(new SysRoleAuthority(r.getId(), a.getId()));
                                    List<SysResource> resourceInfo = a.getResourceInfo();
                                    if (CollUtil.isNotEmpty(resourceInfo)) {
                                        resourceInfo.forEach(re -> authorityResource.add(new SysAuthorityResource(a.getId(), re.getId())));
                                    }
                                });
                            }
                        });
                    }
                });
                if (CollUtil.isNotEmpty(sysUserDetails)) sysUserDetailService.saveBatch(sysUserDetails);
                if (CollUtil.isNotEmpty(userRoles)) sysUserRoleService.saveBatch(userRoles);
                if (CollUtil.isNotEmpty(roleAuthority)) sysRoleAuthorityService.saveBatch(roleAuthority);
                if (CollUtil.isNotEmpty(authorityResource)) sysAuthorityResourceService.saveBatch(authorityResource);
                return true;
            }
        }
        return false;
    }

    @Override
    public SysUser queryDetailsV1(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                        .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public SysUser queryDetailsV2(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        else return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectCollection(
                                SysRole.class,
                                SysUser::getRoleInfo,
                                r -> r.collection(
                                        SysAuthority.class,
                                        SysRole::getAuthorityInfo,
                                        a -> a.collection(
                                                SysResource.class, SysAuthority::getResourceInfo
                                        )
                                )
                        )
                        .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                        .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                        .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                        .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                        .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                        .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public IPage<SysUser> queryDetailsV3(Integer pageNum, Integer pageSize, String userName) {
        MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
        if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
        return super.baseMapper.selectJoinPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
    }


    @Override
    public List<SysUser> queryDetailsV3_1(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) return null;
        else return this.selectJoinList(SysUser.class, new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                .in(SysUser::getId, userIds));
    }

    @Override
    public SysUser queryDetailsV4(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        else return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                        .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                        .selectCollection(
                                SysRole.class,
                                SysUser::getRoleInfo,
                                r -> r.collection(
                                        SysAuthority.class,
                                        SysRole::getAuthorityInfo,
                                        a -> a.collection(
                                                SysResource.class, SysAuthority::getResourceInfo
                                        )
                                )
                        )
                        .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                        .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                        .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                        .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                        .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                        .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public IPage<SysUser> queryDetailsV5(Integer pageNum, Integer pageSize, String userName) {
        MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
        if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
        return this.selectJoinListPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
    }
}

controller类

package com.wanger.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wanger.common.util.ApiResult;
import com.wanger.model.entity.SysResource;
import com.wanger.model.entity.SysUser;
import com.wanger.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@RestController
@Api(value = "用户相关接口", tags = {"用户相关接口"})
@RequestMapping("/sysUser")
public class SysUserController {
    @Resource
    private SysUserService sysUserService;

    @ApiOperation(value = "查询用户列表", notes = "查询用户列表", httpMethod = "POST")
    @PostMapping("/pagingQuery")
    public ApiResult<IPage<SysUser>> pagingQuery(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                                 @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize) {
        return new ApiResult<>(sysUserService.page(new Page<>(pageNum, pageSize)));
    }

    @ApiOperation(value = "深翻页测试", notes = "深翻页测试", httpMethod = "POST")
    @PostMapping("/deepPageTurning")
    public ApiResult<IPage<SysResource>> deepPageTurning(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                                         @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize,
                                                         @RequestParam(value = "name", required = false, defaultValue = "") String name,
                                                         @RequestParam(value = "url", required = false, defaultValue = "") String url) {
        return new ApiResult<>(sysUserService.deepPageTurning(pageNum, pageSize, name, url));
    }

    @ApiOperation(value = "添加用户数据", notes = "添加用户数据", httpMethod = "POST")
    @PostMapping("/addData")
    public ApiResult<Boolean> addData(@RequestBody List<SysUser> userList) {
        return new ApiResult<>(sysUserService.addData(userList));
    }

    @ApiOperation(value = "查询用户详情,一对一查询", notes = "查询用户详情", httpMethod = "POST")
    @PostMapping("queryDetailsV1")
    public ApiResult<SysUser> queryDetailsV1(@RequestParam String id) {
        return new ApiResult<>(sysUserService.queryDetailsV1(id));
    }

    @ApiOperation(value = "查询用户详情,一对多查询", notes = "查询用户资源信息", httpMethod = "POST")
    @PostMapping("/queryDetailsV2")
    public ApiResult<SysUser> queryDetailsV2(@RequestParam String id) {
        return new ApiResult<>(sysUserService.queryDetailsV2(id));
    }

    @ApiOperation(value = "查询用户详情,多对多查询", notes = "分页查询查询用户详情", httpMethod = "POST")
    @PostMapping("/queryDetailsV3")
    public ApiResult<IPage<SysUser>> queryDetailsV3(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                                    @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize,
                                                    @RequestParam(value = "name", required = false, defaultValue = "") String userName) {
        return new ApiResult<>(sysUserService.queryDetailsV3(pageNum, pageSize, userName));
    }

    @ApiOperation(value = "查询用户详情,多对多查询,不分页时多对多查询演示", notes = "分页查询查询用户详情,不分页时多对多查询演示", httpMethod = "POST")
    @PostMapping("/queryDetailsV3_1")
    public ApiResult<List<SysUser>> queryDetailsV3_1(@RequestBody List<String> userIds) {
        return new ApiResult<>(sysUserService.queryDetailsV3_1(userIds));
    }

    @ApiOperation(value = "查询用户详情,一对一同时一对多查询", notes = "查询用户详情,同时查询用户资源信息", httpMethod = "POST")
    @PostMapping("/queryDetailsV4")
    public ApiResult<SysUser> queryDetailsV4(@RequestParam String id) {
        return new ApiResult<>(sysUserService.queryDetailsV4(id));
    }

    @ApiOperation(value = "查询用户详情,多对多查询用户所有信息", notes = "分页查询用户详细信息与资源信息", httpMethod = "POST")
    @PostMapping("/queryDetailsV5")
    public ApiResult<IPage<SysUser>> queryDetailsV5(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                                    @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize,
                                                    @RequestParam(value = "name", required = false, defaultValue = "") String userName) {
        return new ApiResult<>(sysUserService.queryDetailsV5(pageNum, pageSize, userName));
    }


}

其他类

统一返回数据类

package com.wanger.common.util;


import com.wanger.common.enums.ResponseCodeEnum;
import lombok.Data;

import java.io.Serializable;

/**
 * @description: 统一响应信息主体
 */
@Data
public class ApiResult<T> implements Serializable {

    private T data;

    private Integer code = ResponseCodeEnum.SUCCESS.getCode();

    private String message = ResponseCodeEnum.SUCCESS.getMessage();

    private static final String TIP_MESSAGE = "当前系统错误,请稍后再试";

    public ApiResult<T> setMessage(String message) {
        this.message = message;
        return this;
    }

    public ApiResult() {
    }

    public ApiResult(T data) {
        this.data = data;
    }

    public ApiResult(T data, String message) {
        this.data = data;
        this.message = message;
    }

    public ApiResult(T data, ResponseCodeEnum responseCode) {
        this.data = data;
        this.code = responseCode.getCode();
        this.message = responseCode.getMessage();
    }

    public ApiResult(Throwable throwable) {
        //获取详细信息,不带Cause
        try {
            this.message = throwable.getMessage();
            this.code = ResponseCodeEnum.FAIL.getCode();
            throwable.printStackTrace();
        } catch (Exception e) {
            this.message = e.getMessage();
            this.code = ResponseCodeEnum.FAIL.getCode();
            e.printStackTrace();
        }

    }

    public ApiResult(Throwable throwable, ResponseCodeEnum code) {
        //获取详细信息,不带Cause
        try {
            this.message = throwable.getMessage();
            this.code = ResponseCodeEnum.FAIL.getCode();
            throwable.printStackTrace();
        } catch (Exception e) {
            this.message = e.getMessage();
            this.code = code.getCode();
            e.printStackTrace();
        }
    }


}

配置类

package com.wanger.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("*")
            .allowCredentials(true)
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .maxAge(3600);
    }
}

package com.wanger.config;

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

@Configuration
@MapperScan("com.wanger.mapper")
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor()
    {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;

    }

}


package com.wanger.config;

import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(true)          // 是否禁用swagger
                .useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
                        .build());
        return securityContexts;
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
//        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("swagger API文档")
                .description("测试接口文档")
                .version("1.0")
                .build();
    }

    private List<ApiKey> securitySchemes() {
        List<ApiKey> apiKeyList = new ArrayList<>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
        return apiKeyList;
    }
}

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wanger</groupId>
    <artifactId>MyBatisJoinTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>
    <dependencies>
        <!--MySQL驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>


        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <!--mybatis-plus-join-->
        <dependency>
            <groupId>com.github.yulichang</groupId>
            <artifactId>mybatis-plus-join</artifactId>
            <version>1.4.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

        <!-- 引入swagger2的jar包 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.5.22</version>
        </dependency>
        <!--引入接口文档页面UI-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.wanger.DemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

application.yml文件

# Tomcat
server:
  tomcat:
    uri-encoding: UTF-8
  port: 8086



spring:
  datasource:
    url: jdbc:mysql://localhost:3306/join_queries?useUnicode=true&characterEncoding=UTF8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
    username: your_username
    password: your_password
    driver-class-name: com.mysql.jdbc.Driver
#    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    # 连接池
    hikari:
      #连接池名
      pool-name: DateHikariCP
      #最小空闲连接数
      minimum-idle: 10
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 180000
      # 连接池最大连接数,默认是10
      maximum-pool-size: 60
      # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
      auto-commit: true
      # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
      max-lifetime: 1800000
      # 数据库连接超时时间,默认30秒,即30000
      connection-timeout: 30000
      connection-test-query: SELECT 1

  # jackson时间格式化
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss

  #    强制将数字转换为字符串,防止精度丢失
  #    generator:
  #      write_numbers_as_strings: true
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
      enabled: true

#mybatis
mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.wanger.*



;