飞道的博客

Spring Boot(十一)集成MyBatis-Plus

476人阅读  评论(0)

MyBatis-Plus

官网

个人白话解释:简单的CRUD直接通过方法调用,无需多写接口和xml,像jpa那样调用

愿景
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

更多介绍请看官网说明

快速开始

  1. 引入依赖
<dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>
        <dependency> 
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.2-jre</version>
        </dependency>
    </dependencies>

说明核心依赖 mybatis-plus-boot-starter

项目整体目录结构

数据库准备

-- 用户表:user
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` BIGINT(20) PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
  `name` VARCHAR(30) DEFAULT NULL COMMENT '姓名',
  `age` INT(11) DEFAULT NULL COMMENT '年龄',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  `manager_id` BIGINT(20) DEFAULT NULL COMMENT '直属上级id',
  `create_time` DATETIME(0) DEFAULT NULL COMMENT '创建时间',
  `update_time` DATETIME DEFAULT NULL COMMENT '修改时间',
  `version` INT(11) DEFAULT '1' COMMENT '版本',
  `deleted` INT(1) DEFAULT '0' COMMENT '逻辑删除标识(0.未删除,1.已删除)' 
) ENGINE=INNODB CHARSET=UTF8;
INSERT INTO `user`(`id`,`name`,`age`,`email`,`manager_id`,`create_time`) VALUES
(1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL, '2019-01-11 14:20:20'),
(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553, '2019-02-05 11:12:22'),
(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385, '2019-02-14 08:31:16'),
(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385, '2019-01-14 09:15:15'),
(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385, '2019-01-14 09:48:16');

配置文件

application.yml

# 配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

# 配置日志
logging:
  level:
    root: warn
    com.zou.dao: trace
  pattern:
    console: '%p%m%n'

MyBatisPlusConfig 配置类

@EnableTransactionManagement
@Configuration
@MapperScan("com.zou.dao")
public class MyBatisPlusConfig {
	
	// 分页插件配置,如果不需要配置分页插件可以省略这个配置类,
	//然后将 @MapperScan("com.zou.dao")配置在springBoot启动类上即可
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

}

简单CRUD

  1. 新建实体类

User

@Data
public class User {

    private Long id;

    private String name;

    private Integer age;

    private String email;

    private Long managerId;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;
}

传统 mybatis写CRUD需要写接口加xml来完成,这里MyBatis-Plus直接帮我们封装好了简单的单表CRUD,我们写的mapper接口继承 BaseMapper这个泛型接口即可,其中T为你要操作的实体类

UserMapper

@Repository
public interface UserMapper extends BaseMapper<User> {

// 自定义分页
IPage<User> selectPage(Page<User> page,
                           @Param("User") User user);

}

我们可以看到BaseMapper源码中已经给我们封装好了大量的单表操作

只需要这样我们就可以完成简单的CRUD了

创建一个测试类试试吧


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zou.Application;
import com.zou.dao.UserMapper;
import com.zou.entity.User;
import com.zou.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;
import java.util.List;

/**
 * @author WH
 * @version 1.0
 * @date 2020/5/5 11:23
 * @Description TODO
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SelectTest {
    static User user;

    static {
        user = new User();
        user.setName("阿离");
        user.setAge(18);
        user.setEmail("641884200@qq.com");
    }

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    /**
     * 通过id查询
     * SELECT id,name,age,email,manager_id,create_time
     *  FROM user
     *  WHERE id=1088248166370832385;
     */
    @Test
    public void selectById() {
        User user = userMapper.selectById(1088248166370832385L);
    }

    /**
     * 条件查询
     * SELECT id,name,age,email,manager_id,create_time
     *  FROM user
     *  WHERE (name = '阿离' AND age > 18 OR email IS NOT NULL);
     */
    @Test
    public void selectByCondition() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name", "阿离").gt("age", 18).or().isNotNull("email");
        List<User> users = userMapper.selectList(wrapper);
        print(users);
    }



    /** 通过user 查询
     * SELECT id,name,age,email,manager_id,create_time
     *  FROM user
     *  WHERE name='阿离' AND age=18 AND email='641884200@qq.com';
     */
    @Test
    public void selectByUser() {
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        List<User> users = userMapper.selectList(wrapper);
        print(users);

    }

    /**
     *  lambda 条件构造器 防误写
     * SELECT id,name,age,email,manager_id,create_time,update_time
     *  FROM user
     *  WHERE (age LIKE '%雨%' AND (age < 40 OR email IS NOT NULL));
     */
    @Test
    public void selectLambda() {

        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.like(User::getAge, "雨").
                and(q -> q.lt(User::getAge, 40).or().isNotNull(User::getEmail));
        userMapper.selectList(lambda);
    }

    /**
     * 拼接在sql最后
     * SELECT id,name,age,email,manager_id,create_time
     *  FROM user
     *  WHERE (age IN (30,31,32))
     *  LIMIT 1;
     */
    @Test
    public void selectOne() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.in("age", Arrays.asList(30, 31, 32)).last("limit 1");
        List<User> users = userMapper.selectList(wrapper);
    }

    /**
     *  查询指定字段
     */
    @Test
    public void selectColum() {
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        wrapper.select("name", "age");
        userMapper.selectList(wrapper);

    }

    /**
     * 排除指定字段
     * SELECT id,name,manager_id,create_time,update_time
     *  FROM user
     *  WHERE name='阿离' AND age=18 AND email='641884200@qq.com';
     */
    @Test
    public void selectExclude() {
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        wrapper.select(User.class, s ->
            !s.getColumn().equals("email") && !s.getColumn().equals("age")
        );
        List<User> users = userMapper.selectList(wrapper);


    }

    /**
     * 分组排序求和
     * SELECT avg(age) age,min(id)
     *  FROM user
     *  WHERE name='阿离' AND age=18 AND email='641884200@qq.com' GROUP BY id HAVING avg(age)<30;
     */
    @Test
    public void selectGroupBy() {
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        wrapper.select("avg(age) age", "min(id)").groupBy("id")
                .having("avg(age)<{0}", 30);
        List<User> users = userMapper.selectList(wrapper);

    }


    /**
     * 分页
     */
    @Test
    public void selectPage() {
        LambdaQueryWrapper<User> lambda = new LambdaQueryWrapper<>();
        lambda.ge(User::getAge,26).orderByDesc(User::getCreateTime);
        Page<User> page = new Page<> (1,2);
        IPage<User> userIPage = userMapper.selectPage(page, lambda);
        System.out.println("总页数:"+userIPage.getPages());
        System.out.println("总记录数:"+userIPage.getTotal());
        List<User> list = userIPage.getRecords();
        print(list);
    }

    /**
     * 一条sql不查询总记录数 减少性能消耗
     */
    @Test
    public void selectPageNotCount() {
        LambdaQueryWrapper<User> lambda = new LambdaQueryWrapper<>();
        lambda.ge(User::getAge,26).orderByDesc(User::getCreateTime);
        Page<User> page = new Page<> (1,2, false);//不查记录数
        IPage<User> userIPage = userMapper.selectPage(page, lambda);
        System.out.println("总页数:"+userIPage.getPages());
        System.out.println("总记录数:"+userIPage.getTotal());
        List<User> list = userIPage.getRecords();
        print(list);
    }

    /**
     * 自定义分页
     */
    @Test
    public void selectCustom() {
        Page<User> page = new Page<>(1, 3);
        IPage<User> userIPage = userMapper.selectPage(page, user);
        System.out.println("总页数:"+userIPage.getPages());
        System.out.println("总记录数:"+userIPage.getTotal());
        print(userIPage.getRecords());

    }



    public static void print(List<User> users) {
        users.forEach(s -> System.out.println("姓名:" + s.getName()));
    }


}

查询中包含了单表分页,自定义分页update、delete操作与查询类似

通用service

如果BaseMapper操作没有满足还可以进一步使用 IService,里面有更多的操作数据库方法

用法很简单,最好的做法是在mapper封装一层DAO,不要在Service层继承,那样dao就可以拥有所有mybatis方法了,大致使用如下

详细方法可以参考官网

源码下载

源码


转载:https://blog.csdn.net/qq_42651904/article/details/105934933
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场