开发利器 --mybatis-plus ,再也不用写单表CRUD的重复代码了

410 阅读4分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

一、是什么?

mybatis-plus 是 Mybatis 增强工具包 - 只做增强不做改变,简化CRUD操作。

  • 无侵入:Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做增强不做改变,引入 Mybatis-Plus 不会对您现有的 Mybatis 构架产生任何影响,而且 MP 支持所有 Mybatis 原生的特性
  • 依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring
  • 损耗小:启动即会自动注入基本CURD,性能基本无损耗,直接面向对象操作
  • 通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 多种主键策略:支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题
  • 支持ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作
  • 支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(P.S. 比 Mybatis 官方的 Generator 更加强大!)
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere ) -内置分页插件:基于Mybatis物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于写基本List查询
  • 内置性能分析插件:可输出Sql语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,预防误操作

二、官方参考文档 baomidou.com/guide/

三、强大的 wrapper

mybatis-plus的wapper继承图

在这里插入图片描述

Wraper的介绍:

  1. Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示
  2. AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
  3. AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
  4. LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
  5. LambdaUpdateWrapper : Lambda 更新封装Wrapper
  6. QueryWrapper : Entity 对象封装操作类,不是用lambda语法
  7. UpdateWrapper : Update 条件封装,用于Entity对象更新操作

例如:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "zhangsan");
queryWrapper.ge("age", "18");
.......// 后面可以继续使用下图的函数,用于拼接sql。

函数说明:

AbstractWrapper的子类均可使用下面的函数。 在这里插入图片描述

四、代码实战

源代码地址github.com/Dr-Water/my…

示例源代码目录结构: 在这里插入图片描述

  1. 新建一个springboot 工程 引入以下依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </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>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--mybatis-plus的核心依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>
  1. 数据库配置文件:
# 应用名称
spring.application.name=mp
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=UTC&characterEncoding=UTF-8
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
# 打印 mybatis-plus 的sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#mybatis mapper 定义的位置
mybatis-plus.mapper-locations= classpath*:/mappers/*.xml
#实体扫描,多个package用逗号或者分号分隔
mybatis-plus.typeAliasesPackage=com.ratel.mp.entity
  1. entity
package com.ratel.mp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Builder;
import lombok.Data;


/**
 * @业务描述:
 * @package_name: com.ratel.mp.entity
 * @project_name: mybatis-plus-demo
 * @author: ratelfu@qq.com
 * @create_time: 2020-12-13 10:14
 * @copyright (c) ratelfu 版权所有
 */
@Data
@Builder
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    private String email;
}

  1. dao
package com.ratel.mp.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ratel.mp.entity.User;
import org.apache.ibatis.annotations.Param;

/**
 * @业务描述:
 * @package_name: com.ratel.mp
 * @project_name: mybatis-plus-demo
 * @author: ratelfu@qq.com
 * @create_time: 2020-12-02 20:45
 * @copyright (c) ratelfu 版权所有
 */
public interface UserDao extends BaseMapper<User> {
    /**
     * 自定义的getById
     * @param id
     * @return
     */
    User myGetById(@Param("id") Integer id);
}

  1. mapper
<?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.ratel.mp.dao.UserDao">
<!--自定义的sql写在这里-->

    <select id="myGetById" resultType="com.ratel.mp.entity.User">
        select * from user where id=#{id}
    </select>
</mapper>
  1. service
package com.ratel.mp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ratel.mp.entity.User;

/**
 * @业务描述:
 * @package_name: com.ratel.mp.service
 * @project_name: mybatis-plus-demo
 * @author: ratelfu@qq.com
 * @create_time: 2020-12-13 10:34
 * @copyright (c) ratelfu 版权所有
 */
public interface UserService extends IService<User> {
    User myGetById(Integer id);
}

  1. serviceImpl
package com.ratel.mp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ratel.mp.dao.UserDao;
import com.ratel.mp.entity.User;
import com.ratel.mp.service.UserService;
import org.springframework.stereotype.Service;

/**
 * @业务描述:
 * @package_name: com.ratel.mp.service
 * @project_name: mybatis-plus-demo
 * @author: ratelfu@qq.com
 * @create_time: 2020-12-13 10:36
 * @copyright (c) ratelfu 版权所有
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    @Override
    public User myGetById(Integer id) {
    	//baseMapper为ServiceImpl 定义好且已经注入的,这里无需再次 定义和注入
        return baseMapper.myGetById(id);
    }
}

  1. 简单的crud

package com.ratel.mp;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ratel.mp.entity.User;
import com.ratel.mp.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MpApplicationTests {

    @Autowired
    private UserService userService;

    @Test
    void queryTest(){
        //普通写法
        List<User> userList = userService.list(Wrappers.<User>query().eq("id",1));
        System.out.println(userList);

        //lambda写法
        List<User> list = userService.list(Wrappers.<User>lambdaQuery().eq(User::getId,1));
        list.forEach(System.out::println);

        //new LambdaQueryWrapper<>(entity) 这种写法会将 entity中不为null的属性 拼接成where后的条件,且是 拼接出来是:eq(eg: id=1 and name = 'zs'...)
        // 便于日常开发使用,比如说 前端会根据 id/name/age/email 这四种的任意一个或多个 进行查询,list,手动一个一个 .eq 太麻烦,就可以使用这种方式
        List<User> list2 = userService.list(Wrappers.<User>lambdaQuery(User.builder().id(1).build()));
        list.forEach(System.out::println);
    }
    @Test
    void saveTest(){
        //由于主键是自增的所以这里就不用设置id的值了
        boolean isSuccess = userService.save(User.builder().name("zhangsan").age(18).email("zhangsan@qq.com").build());
        System.out.println(isSuccess);
    }
    @Test
    void updateTest(){
        User user = User.builder().name("zhangsan2").age(20).email("zhangsan2@qq.com").build();
        boolean isSuccess = userService.update(user, Wrappers.<User>update().eq("id",13));
        System.out.println(isSuccess);

        //用于构成 update语句的where部分
        User condition = User.builder().id(13).build();
        UpdateWrapper<User> updateWrapper = Wrappers.<User>update(condition)
                .setSql("name=" + "'zhangsan3'," + "age=" + 18); //设置 set 语句(name=zs,age=18...)
        boolean isSuccess2 = userService.update(updateWrapper);
        System.out.println(isSuccess2);
    }

    @Test
    void deleteTest(){
        boolean isSuccess = userService.removeById(14);
        System.out.println(isSuccess);
        //删除一个不存在的数据 返回false
        boolean isSuccess2 = userService.removeById(-1);
        System.out.println(isSuccess2);
    }
    //测试自定义代码
     @Test
    void myGetByIdTest(){
        User user = userService.myGetById(1);
        System.out.println(user);
    }

}

五参考文章

  1. Mybatis Plus的BaseMapper的方法是如何注入的
  2. Mybatis plus强大的条件构造器QueryWrapper条件构造器基础方法解释