编程随笔 编程随笔
  • 前端
  • 后端
  • 嵌入式
  • 星球项目
  • 开源项目
  • 海康AGV
  • 四向车
  • 工具类
  • 项目仓库

    • 部署仓库 (opens new window)
    • 代码仓库 (opens new window)
  • vuepress插件

    • 自动生成导航栏与侧边栏 (opens new window)
    • 评论系统 (opens new window)
    • 全文搜索 (opens new window)
    • 选项卡 (opens new window)
    • 自动生成sitemap (opens new window)
  • 自主开发插件

    • 批量操作frontmatter (opens new window)
    • 链接美化 (opens new window)
    • 折叠代码块 (opens new window)
    • 复制代码块 (opens new window)

liyao52033

走运时,要想到倒霉,不要得意得过了头;倒霉时,要想到走运,不必垂头丧气。心态始终保持平衡,情绪始终保持稳定,此亦长寿之道
  • 前端
  • 后端
  • 嵌入式
  • 星球项目
  • 开源项目
  • 海康AGV
  • 四向车
  • 工具类
  • 项目仓库

    • 部署仓库 (opens new window)
    • 代码仓库 (opens new window)
  • vuepress插件

    • 自动生成导航栏与侧边栏 (opens new window)
    • 评论系统 (opens new window)
    • 全文搜索 (opens new window)
    • 选项卡 (opens new window)
    • 自动生成sitemap (opens new window)
  • 自主开发插件

    • 批量操作frontmatter (opens new window)
    • 链接美化 (opens new window)
    • 折叠代码块 (opens new window)
    • 复制代码块 (opens new window)
  • springboot

    • MyBatis Plus使用
      • 1.常用CRUD及基本流程
      • 2.分页插件使用
      • 3.判断数据是否已存在
    • springboot2引入swagger3
    • EasyCaptcha验证码存入redis的使用
    • 常用方法
    • Elasticsearch全文搜索
    • canal同步mysql数据到es中
    • SpringSecurity使用
    • StringUtils 工具类使用
    • HTTP各种参数发送
    • EasyExcel之Excel导入导出
    • EasyExcel具体使用
    • FreeMarker 模板引擎入门
    • FreeMarker生成文件及WEB使用
    • TrueLicense 创建及安装证书
  • 服务器相关

  • 腾讯云cos对象操作

  • 后端
  • springboot
华总
2023-08-24
0
0
目录

MyBatis Plus使用原创

提示

maven依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.2</version>
</dependency>
1
2
3
4
5

yml配置

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-field: isDelete # 全局逻辑删除的实体字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

1
2
3
4
5
6
7
8
9
10

# 1.常用CRUD及基本流程

基本流程 mapper.xml => mapper => serviceImpl => service => controller => 前端
1

# 1.1 CRUD使用

mapper,mapper.xml及基本的service层由MybatisX生成,基本使用直接在controller层调用即可,如下

   @GetMapping("/")
    public Website listConfig() {
        QueryWrapper<Website> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("config");
        return websiteService.getOne(queryWrapper);
    }
1
2
3
4
5
6

也可在service层自定义接口,serviceImpl层写具体逻辑,controller层调用

 // service层
boolean userLogin(String userAccount, String userPassword);

// serviceImpl层
 @Override
public boolean userLogin(String userAccount, String userPassword) {

    //密码字段加密
    String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

    User user = new User();
    user.setUserAccount(userAccount);
    user.setUserPassword(encryptPassword);
    return this.save(user);
}

//controller层调用
    @PostMapping("/add")
    public Result<String> add(@Validated @RequestBody UserQueryRequest userQueryRequest) {
       String userAccount = userQueryRequest.getUserAccount();
       String password = userQueryRequest.getUserPassword();

        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("userAccount",userAccount);
        Long count = userService.count(wrapper);
        if(count > 0){
            return Result.handle(ErrorCode.OPERATION_ERROR.getCode(),ErrorCode.OPERATION_ERROR.getMessage(), Collections.singletonList("账户已存在"));
        }

       boolean result = userService.userLogin(userAccount,password);
       if (result) {
          return Result.success("保存成功");
       } else {
          return Result.failure(ErrorCode.SYSTEM_ERROR);
       }
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 1.2 自定义错误码及错误封装

1.2.1 自定义错误码

// 自定义错误码
public enum ErrorCode {

    //错误代码
    PARAMS_ERROR(40000, "请求参数错误",""),
    NOT_LOGIN_ERROR(40100, "未登录", ""),
    NO_AUTH_ERROR(40101, "权限不足,请用管理员账号登录", ""),
    NOT_FOUND_ERROR(40400, "请求数据不存在", ""),
    FORBIDDEN_ERROR(40300, "禁止访问", ""),
    SYSTEM_ERROR(50000, "系统错误", ""),
    NOT_EQUALS(66666,"两次密码不一致",""),
    OPERATION_ERROR(50001, "操作失败", "");


    /**
     * 状态码
     */
    private final int code;

    /**
     * 信息
     */
    private final String message;

    /**
     * 数据
     */
    private final String data;

    // 构造函数,该构造函数需要传入一个整数代码、消息和数据字符串。
    ErrorCode(int code, String message, String data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public String getData() {
        return data;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

1.2.2 自定义返回类

@Data
public class Result<T> {

    private int code;  // 响应状态码
    private String message;  // 响应消息
    private T data;  // 响应数据


    // 构造函数
    public Result(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    //参数检验失败函数,在GlobalControllerAdvice.java里调用
    public Result() {

    }

    // 成功时的静态工厂方法
    public static <T> Result<T> success(T data) {

        return new Result<T>(200, "操作成功", data);
    }

    // 失败时的静态工厂方法
    public static <T> Result<T> failure(ErrorCode errorCode) {

        return new Result<T>(errorCode.getCode(), errorCode.getMessage(), (T) errorCode.getData());
    }

    // 参数检验失败的提示
    public static Result handle(int value, String badRequestMsg, List<String> collect) {
        return new Result(value,badRequestMsg, collect);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

1.2.3 参数校验类

// 参数检验
@Data
public class UpdateQueryRequest implements Serializable {

    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    @NotNull(message = "id不能为空")
    private Long id;

    @Size(min = 8, max = 16, message = "密码长度必须是8-16个字符")
    private String userPassword;

    @Size(min = 8, max = 16, message = "校验密码长度必须是8-16个字符")
    private String checkPassword;

    private static final long serialVersionUID = 1L;

}

// 获取参数检验注解里的说明并组合成数组传给前端
@RestControllerAdvice
public class GlobalControllerAdvice {

    // <1> 处理 form data方式调用接口校验失败抛出的异常
    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        // 组合参数检验类里的说明
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getDefaultMessage())
                .collect(Collectors.toList());
        return new Result().handle(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage(), collect);
    }
    // <2> 处理 json 请求体调用接口校验失败抛出的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        // 组合参数检验类里的说明
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getDefaultMessage())
                .collect(Collectors.toList());
        return Result.handle(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage(), collect);
    }
    // <3> 处理单个参数校验失败抛出的异常
    @ExceptionHandler(ConstraintViolationException.class)
    public Result constraintViolationExceptionHandler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        // 组合参数检验类里的说明
        List<String> collect = constraintViolations.stream()
                .map(o -> o.getMessage())
                .collect(Collectors.toList());
        return Result.handle(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage(), collect);
    }
}

// controller层使用
@Validated  //类上加@Validated 注解
public class UserController {
   @PostMapping("/add")
    // 方法参数里加上@Validated 注解即可实现对参数的校验
    // 有其他的实体类只需在对应字段添加相应注解及说明,在控制层类和方法上加上@Validated 注解即可
    public Result<String> add(@Validated @RequestBody UserQueryRequest userQueryRequest) {
       String userAccount = userQueryRequest.getUserAccount();
       String password = userQueryRequest.getUserPassword();

        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("userAccount",userAccount);
        Long count = userService.count(wrapper);
        if(count > 0){
            return Result.handle(ErrorCode.OPERATION_ERROR.getCode(),ErrorCode.OPERATION_ERROR.getMessage(), Collections.singletonList("账户已存在"));
        }

       boolean result = userService.userLogin(userAccount,password);
        // 自定义返回类及错误码
       if (result) {
          return Result.success("保存成功");
       } else {
          return Result.failure(ErrorCode.SYSTEM_ERROR);
       }
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

# 2.分页插件使用

# 2.1 添加配置文件

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 2.2 mapper层自定义分页接口

IPage<UserVO> selectMyPage(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
1

Constants.WRAPPER则是一个固定的字符串,用于表示Wrapper实例的标识符,可以在使用Wrapper实例的时候作为参数名称传递给Mapper接口方法,以便MyBatis-Plus能够正确地解析Wrapper实例并生成SQL语句

# 2.3 mapper.xml文件配置

 <select id="selectMyPage" resultType="com.xiaoying.hello.model.VO.UserVO">
        select * from user ${ew.customSqlSegment}
    </select>
1
2
3

${ew.customSqlSegment} 是一个占位符,用于动态拼接 SQL 语句。${ew.customSqlSegment} 中的 ew 是一个Wrapper实例的变量名,用于表示Wrapper实例中的自定义 SQL 片段,customSqlSegment 是一个Wrapper实例中的方法名,用于表示自定义 SQL 片段的名称。当我们使用 Wrapper 来构建查询条件时,可以通过调用 Wrapper 中的自定义 SQL 方法来构建自定义 SQL 片段。

# 2.4 service层配置

IPage<UserVO> getUserPage(Page<User> userPage, ListQueryRequest listQueryRequest);
1

userpage表示分页对象,listQueryRequest为dto,表示分页参数

# 2.5 serviceImpl层配置

  @Override
    public IPage<UserVO> getUserPage(Page<User> userPage, ListQueryRequest listQueryRequest) {

        // 获取所需参数
        String UserAccount = listQueryRequest.getUserAccount();
        String userName = listQueryRequest.getUserName();
        String userProfile = listQueryRequest.getUserProfile();
        String searchText = listQueryRequest.getSearchText();
        String createTime = listQueryRequest.getCreateTime();
        long current = userPage.getCurrent(); //当前页数
        long size = userPage.getSize(); //每页条数

        //构造查询条件
        QueryWrapper<User> Wrapper = new QueryWrapper<>();
        Wrapper.like(StringUtils.isNoneBlank(UserAccount),"UserAccount",UserAccount);
        Wrapper.like(StringUtils.isNotBlank(userName),"userName",userName);
        Wrapper.like(StringUtils.isNotBlank(userProfile),"userProfile",userProfile);
        Wrapper.like(StringUtils.isNotBlank(createTime),"createTime", createTime);
        if(StringUtils.isNotBlank(searchText)){
            Wrapper.like(StringUtils.isNotBlank(userName),"userName",userName).or()
                    .like(StringUtils.isNotBlank(UserAccount),"UserAccount",UserAccount);
        }

        //分页查询
        Page<User> page = new Page<>(current,size);
        return userMapper.selectMyPage(page,Wrapper);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 2.6 controller配置

  @PostMapping("/list")
    public Result<IPage<UserVO>> list(@RequestBody ListQueryRequest listQueryRequest) {

        long current = listQueryRequest.getCurrent();
        long size = listQueryRequest.getSize();

        Page<User> page = new Page<>(current,size);
        IPage<UserVO> mapIPage = userService.getUserPage(page,listQueryRequest);
        return Result.success(mapIPage);
    }
1
2
3
4
5
6
7
8
9
10

# 2.7 VO层配置

@Data
public class UserVO implements Serializable {
    /**
     * 账号
     */
    private String userAccount;

    /**
     * 用户昵称
     */
    private String userName;

    /**
     * 用户头像
     */
    private String userAvatar;

    /**
     * 用户简介
     */
    private String userProfile;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
    private LocalDateTime createTime;

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

枚举需要返回的字段,可以进行脱敏,包装类转换等操作

# 3.判断数据是否已存在

要使用 MyBatis Plus 来判断数据是否已存在,可以使用 MyBatis Plus 提供的通用方法 `selectCount`。以下是一个示例:

   QueryWrapper<ApiInfo> queryWrapper = new QueryWrapper<>();
   String url = apiAddRequest.getUrl();
   queryWrapper.eq("url", url);
   long count = apiInfoMapper.selectCount(queryWrapper);
   ThrowUtils.throwIf(count > 0, ErrorCode.EXIST_ERROR,"接口已存在");

在上述代码中,我们使用 `QueryWrapper` 创建一个查询条件,使用 `eq` 方法指定要查询的数据列和要匹配的值。然后,我们使用 `selectCount` 方法执行查询,该方法会返回匹配查询条件的数据行数。最后,我们将结果与 0 进行比较,如果大于 0 则表示数据已存在,返回 `true`;否则,表示数据不存在,返回 `false`。

请将上述代码中的 `Entity` 替换为您的实体类名称,并将 `data_column` 替换为您要进行判断的数据列名称。
1
2
3
4
5
6
7
8
9
10
11
#后端#springboot#MyBatis Plus
上次更新: 2025/02/18 14:46:10
springboot2引入swagger3

springboot2引入swagger3→

最近更新
01
jFlash使用 原创
03-24
02
中央仓库上传指南 原创
03-23
03
模板生成工具 原创
02-18
04
RTC实时时钟 原创
02-12
05
keil调试 原创
01-21
更多文章>
Copyright © 2023-2025 liyao52033  All Rights Reserved
备案号:鄂ICP备2023023964号-1    
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式