MyBatis-Plus入门,看这一篇就足够了

文章设计源代码和笔记:gitee

一、Mybatis-Plus

简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

我们的愿景是成为 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持数据库

  • mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver 、 presto
  • 达梦数据库 、 虚谷数据库 、 人大金仓数据库

框架结构

代码托管

Gitee | Github

二、快速入门

地址:https://mp.baomidou.com/guide/quick-start.html#初始化工程

使用第三方组件

  1. 导入对应依赖
  2. 研究依赖配置
  3. 代码如何编写
  4. 提高扩展技术能力!

步骤

  1. 创建数据库mybatis_plus
  2. 创建user表,插入数据
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
  1. 编写项目,初始化项目! 使用SpringBoot初始化!
  2. 导入依赖

    org.springframework.bootspring-boot-starter-web

    org.springframework.bootspring-boot-starter-testtest
    
        
            org.junit.vintagejunit-vintage-engine<
        
    



    mysql
    mysql-connector-java8.0.20



    org.projectlombok
    lombok
    1.18.12



    com.baomidou
    mybatis-plus-boot-starter3.3.1

说明:我们使用mybatis-plus可以节省大量代码,尽量不要同时导入mybatis和mybatis-plus!版本差异!

  1. 配置数据库,和mybatis一样
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username=mybatis_plus
spring.datasource.password=mybatis_plus123
  1. 在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@MapperScan("com.godfrey.mapper")
@SpringBootApplication
public class MybatisPlusApplication {

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

}
  1. 编码

编写实体类 User.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编写Mapper类 UserMapper.java

@Mapper
public interface UserMapper extends BaseMapper {
}

8.使用

添加测试类,进行功能测试:

@SpringBootTest
class MybatisPlusApplicationTests {

    @Resource
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //查询全部用户
        //参数是一个Wrapper,条件构造器
        List users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

控制台输出:

User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])

小结

通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!

从以上步骤中,我们可以看到集成MyBatis-Plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。

三、配置日志

# 配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

四、CRUD扩展

插入操作

//测试插入
@Test
public void testInsert(){
    User user = new User();
    user.setName("淮城一只猫");
    user.setAge(5);
    user.setEmail("[email protected]");
    int result = userMapper.insert(user); //自动生成id
    System.out.println(result); //受影响的行数
    System.out.println(user); //发现id自动回填
}

MyBatis-Plus入门,看这一篇就足够了_第1张图片

数据库插入的id默认是全局唯一id

主键生成策略

默认ID_WORKER,全局唯一id

分布式系统唯一id生成方案汇总

雪花算法:

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键自增

我们需要配置注解自增:

  1. 实体类字段上:@TableId(type = IdType.AUTUO)
  2. 数据库字段一定要自增

MyBatis-Plus入门,看这一篇就足够了_第2张图片

3.再次测试插入即可!

其余的策略解释

public enum IdType {
    AUTO(0), //id自增
    NONE(1), //未设置主键
    INPUT(2), //手动输入
    ID_WORKER(3), //默认值,全局唯一id
    UUID(4), //全局唯一id,uuid
    ID_WORKER_STR(5); //ID_WORKER的字符串表示法
}

更新操作

//测试更新
@Test
public void testUpdate(){
    User user = new User();
    user.setId(6L);
    user.setName("我的博客叫:淮城一只猫");
    user.setAge(6);
    user.setEmail("[email protected]");
    //注意:updateById参数是一个对象
    int result = userMapper.updateById(user); //自动生成id
    System.out.println(result); //受影响的行数
}

自动填充

创建时间、修改时间!这些操作一般自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不建议这么做)

  1. 在表中新增字段create_time、update_time

MyBatis-Plus入门,看这一篇就足够了_第3张图片

  1. 再次测试插入方法,需要先把实体类同步!
private Date creteTime;
private Date updateTime;

MyBatis-Plus入门,看这一篇就足够了_第4张图片

方式二:代码级别

  1. 输出数据库中的默认值、更新操作

MyBatis-Plus入门,看这一篇就足够了_第5张图片

  1. 在实体类字段属性上需要注释
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date creteTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
  1. 编写处理器处理注解!
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler{
    //插入时填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //更新时填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
  1. 测试插入
  2. 测试更新、观察时间即可!

乐观锁

乐观锁:顾名思义乐观,它总是认为不会出现问题,无论干什么都不去上锁!如果出现问题,再次更新值测试

悲观锁:顾名思义悲观,它总是认为会出现问题,无论干什么都会加上锁!再去操作

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

测试MP乐观锁插件

  1. 数据库中添加version字段!

MyBatis-Plus入门,看这一篇就足够了_第6张图片

  1. 实体类添加对应字段
@Version  //乐观锁注解
private Integer version;
  1. 注册组件
@MapperScan("com.godfrey.mapper")
@EnableTransactionManagement  //自动管理事务(默认也是开启的)
@Configuration  //配置类
public class MybaitsPlusConfig {

    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
  1. 测试一下
//测试乐观锁成功!
@Test
public void testOptimisticLocker1() {
    //1.查询用户信息
    User user = userMapper.selectById(1L);
    //2.修改用户信息
    user.setName("godfrey");
    user.setEmail("[email protected]");
    //3.执行更新操作
    userMapper.updateById(user);
}


//测试乐观锁失败!多线程下
@Test
public void testOptimisticLocker2() {
    //线程1
    User user1 = userMapper.selectById(1L);
    user1.setName("godfrey111");
    user1.setEmail("[email protected]");

    //模拟另外一个线程执行插队操作
    User user2 = userMapper.selectById(1L);
    user2.setName("godfrey222");
    user2.setEmail("[email protected]");
    userMapper.updateById(user2);

    //自旋锁多次操作尝试提交
    userMapper.updateById(user1);
}

MyBatis-Plus入门,看这一篇就足够了_第7张图片

查询操作

//测试查询
@Test
public void testSelectById() {
    User user = userMapper.selectById(1L);
    System.out.println(user);
}

//测试批量查询
@Test
public void testSelectByBatchId() {
    List users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
    users.forEach(System.out::println);
}

//条件查询之一 使用map操作
@Test
public void testSelectBatchIds() {
    HashMap map = new HashMap<>();
    //自定义查询
    map.put("name","Tom");
    map.put("age",28);

    List users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

分页查询

分页在网站中使用非常多!

  1. 原始limit进行分页
  2. pageHelper第三方插件
  3. MP其实也内置了分页插件

如何使用?

  1. 配置分页插件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}
  1. 直接使用Page对象即可!
//测试分页查询
@Test
public void testPage() {
    //参数一:当前页
    //参数二:页面大小
    //使用了分页插件之后,所有的分页操作页变得简单了
    Page page = new Page<>(1,5);
    userMapper.selectPage(page,null);

    page.getRecords().forEach(System.out::println);
    System.out.println(page.getTotal());
}

删除操作

基本的删除操作

//通过id删除
@Test
public void testDeleteById() {
    userMapper.deleteById(8L);
}

//通过id批量删除
@Test
public void testDeleteBatchId() {
    userMapper.deleteBatchIds(Arrays.asList(6L, 7L));
}

//通过map删除
@Test
public void testDeleteMap() {
    HashMap map = new HashMap<>();
    map.put("name", "godfrey");
    userMapper.deleteByMap(map);
}

我们在工作中会遇到一些问题:逻辑删除!

逻辑删除

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!delete=0 => delete=1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

测试一下:

  1. 在数据表中增加deleted字段

MyBatis-Plus入门,看这一篇就足够了_第8张图片

  1. 实体类中同步属性
//逻辑删除字段
private Integer deleted;
  1. 配置
# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-field=deleted # 全局逻辑删除的实体字段名
mybatis-plus.global-config.db-config.logic-delete-value=1 # 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-not-delete-value=0 # 逻辑未删除值(默认为 0)
  1. 测试一下删除

MyBatis-Plus入门,看这一篇就足够了_第9张图片

MyBatis-Plus入门,看这一篇就足够了_第10张图片

以上的所有CRUD操作及其扩展操作,我们都必须精通掌握!会大大提高工作和写项目效率

性能分析插件

我们在开发中,会遇到一些慢sql,我们有必要把它揪出来 。测试!druid...

MP也提供性能分析插件,如果超过这个时间就停止运行!官方3.1.0以上版本推荐使用p6spy!

  1. 导入依赖


    p6spy
    p6spy
    3.9.0

  1. 修改数据库连接配置
# 数据库连接配置
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
  1. 新建spy.properties 并设置参数
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式gui
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
  1. 测试使用!(只要超过了规定时间就会抛出异常)

MyBatis-Plus入门,看这一篇就足够了_第11张图片

注意,插件会影响性能,建议开发和测试环境下使用

条件构造器

  1. 测试一
@Test
void test1() {
    //查询name不为空的用户,并且邮箱不为空的,年龄大于等于12
    QueryWrapper wapper = new QueryWrapper<>();
    wapper.isNotNull("name")
            .isNotNull("email")
            .ge("age", 12);
    userMapper.selectList(wapper).forEach(System.out::println);
}
  1. 测试二
@Test
void test2() {
    //查询名字为Tom
    QueryWrapper wapper = new QueryWrapper<>();
    wapper.eq("name","Tom");
    User user = userMapper.selectOne(wapper);
    System.out.println(user);
}
  1. 测试三
//范围查询
@Test
void test3() {
    //查询年龄在20~30岁之间的用户
    QueryWrapper wapper = new QueryWrapper<>();
    wapper.between("age", 20, 30);//区间
    System.out.println(userMapper.selectCount(wapper));//查询结果数
}
  1. 测试四
//模糊查询
@Test
void test4() {
    //查询名字有
    QueryWrapper wapper = new QueryWrapper<>();
    wapper.notLike("name","e")//%e%
            .likeRight("email","t");//t%
    List> maps = userMapper.selectMaps(wapper);
    maps.forEach(System.out::println);
}
  1. 测试五
//子查询
@Test
void test5() {
    QueryWrapper wapper = new QueryWrapper<>();
    //id在子查询中查出来
    wapper.inSql("id","select id from user where id<3");
    List objects = userMapper.selectObjs(wapper);
    objects.forEach(System.out::println);
}
 
 
  1. 测试六
//排序
@Test
void test6() {
    QueryWrapper wapper = new QueryWrapper<>();
    //通过id进行排序
    wapper.orderByDesc("id");
    userMapper.selectList(wapper).forEach(System.out::println);
}

代码生成器

mapper、pojo、service、controller都给我自己去编写完成!

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

1.EasyCode介绍


1.1 EasyCode是一个什么东西?


EasyCode是基于IntelliJ IDEA Ultimate版开发的一个代码生成插件,主要通过自定义模板(基于velocity)来生成各种你想要的代码。通常用于生成Entity、Dao、Service、Controller。如果你动手能力强还可以用于生成HTML、JS、PHP等代码。理论上来说只要是与数据有关的代码都是可以生成的。


1.2 原理

基于Mybatis底层强大的逆向工程能力和良好的项目架构


1.3 使用环境

IntelliJ IDEA Ultimate版


1.4 支持的数据库类型

因为是基于Database Tool开发,所有Database Tool支持的数据库都是支持的。

包括如下数据库:

  1. MySQL
  2. SQL Server
  3. Oracle
  4. PostgreSQL
  5. Sqlite
  6. Sybase
  7. Derby
  8. DB2
  9. HSQLDB
  10. H2

当然支持的数据库类型也会随着Database Tool插件的更新同步更新。


1.5 功能说明:

  • 支持多表同时操作
  • 支持同时生成多个模板
  • 支持自定义模板
  • 支持自定义类型映射(支持正则)
  • 支持自定义附加列
  • 支持列附加属性
  • 所有配置项目支持分组模式,在不同项目(或选择不同数据库时),只需要切换对应的分组,所有配置统一变化

1.6 功能对比:

功能 Easy Code 其他工具
自定义模板 支持 支持
多表生成 支持 支持
生成方式 无缝集成在项目中 部分工具需要复制粘贴
附加列 支持 不支持
附加列属性 支持 不支持
动态调试模板 支持 不支持
图形化界面 支持 部分支持
使用环境 仅限IDEA 支持各种形式
在线支持 后期扩展 不支持
自定义类型映射 支持 部分支持
全局变量 支持 不支持

2.EasyCode使用


2.1 下载Easy Code插件

MyBatis-Plus入门,看这一篇就足够了_第12张图片


2.2 创建一个SpringBoot项目

MyBatis-Plus入门,看这一篇就足够了_第13张图片

2.3 配置数据源

使用Easy Code一定要使用IDEA自带的数据库工具来配置数据源

MyBatis-Plus入门,看这一篇就足够了_第14张图片.


打开侧边的Database,查看效果

MyBatis-Plus入门,看这一篇就足够了_第15张图片,


提前准备的数据表

MyBatis-Plus入门,看这一篇就足够了_第16张图片,


2.4 自定义生成模板

MyBatis-Plus入门,看这一篇就足够了_第17张图片


第一次安装EasyCode的时候默认的模板(服务于MyBatis)可以生成下面类型的代码

  1. entity.java
  2. dao.java
  3. service.java
  4. serviceImpl.java
  5. controller.java
  6. mapper.xml
  7. debug.json

2.5 以user表为例,根据你定义的模板生成代码,文章的最后贴出我使用的自定义的模板

MyBatis-Plus入门,看这一篇就足够了_第18张图片,


选择模板

MyBatis-Plus入门,看这一篇就足够了_第19张图片,


点击OK之后,就可以看到生成了这些代码

MyBatis-Plus入门,看这一篇就足够了_第20张图片,


2.6 代码展示

实体类层:User.java
package com.godfrey.easycode.entity;

import java.io.Serializable;

/**
 * (User)实体类
 *
 * @author godfrey
 * @since 2020-04-20 19:21:17
 */
public class User implements Serializable {
    private static final long serialVersionUID = 502672392114472688L;
    /**
     * 主键ID
     */
    private Integer id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 邮箱
     */
    private String email;

        
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
        
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
        
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
        
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                "name=" + name +
                "age=" + age +
                "email=" + email +
                '}';
    }
}

Dao数据库访问层:UserDao.java
package com.godfrey.easycode.dao;

import com.godfrey.easycode.entity.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * description : (User)表数据库访问层
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
@Mapper
public interface UserDao {

    /**
     * description : 添加User
     *
     * @param user 实例对象
     * @return 影响行数
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int insert(User user);

    /**
     * description : 删除User
     *
     * @param  id 主键
     * @return 影响行数
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int deleteById(Integer id);

    /**
     * description : 通过ID查询单条数据
     *
     * @param  id 主键
     * @return 实例对象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    User queryById(Integer id);

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List queryAll();

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param  user 实例对象
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List queryAll(User user);

    /**
     * description : 修改User
     *
     * @param  user 根据user的主键修改数据
     * @return 影响行数
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int update(User user);
}

Service服务接口层:UserService.java
package com.godfrey.easycode.service;

import com.godfrey.easycode.entity.User;
import java.util.List;

/**
 * description : (User)表服务接口
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
public interface UserService {

    /**
     * description : 添加User
     *
     * @param  user 实例对象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean insert(User user);

    /**
     * description : 删除User
     *
     * @param  id 主键
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean deleteById(Integer id);

    /**
     * description : 查询单条数据
     * @param  id 主键
     * @return 实例对象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    User queryById(Integer id);

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List queryAll();

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param  user 实例对象
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List queryAll(User user);

    /**
     * description : 修改数据,哪个属性不为空就修改哪个属性
     *
     * @param  user 实例对象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean update(User user);
}

ServiceImpl服务接口实现层:UserServiceImpl.java
package com.godfrey.easycode.service.impl;

import com.godfrey.easycode.entity.User;
import com.godfrey.easycode.dao.UserDao;
import com.godfrey.easycode.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

 /**
  * description : (User)表服务实现类
  *
  * @author godfrey
  * @since  2020-04-20 19:21:17
  **/
@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    protected UserDao userDao;

    /**
     * description : 添加User
     *
     * @param  user 实例对象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean insert(User user) {
        return userDao.insert(user) == 1;
    }

    /**
     * description : 删除User
     *
     * @param  id 主键
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean deleteById(Integer id) {
        return userDao.deleteById(id) == 1;
    }

    /**
     * description : 查询单条数据
     *
     * @param  id 主键
     * @return 实例对象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public User queryById(Integer id) {
        return userDao.queryById(id);
    }

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public List queryAll() {
        return userDao.queryAll();
    }

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param user 实例对象
     * @return 对象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public List queryAll(User user) {
        return userDao.queryAll(user);
    }

    /**
     * description : 修改数据,哪个属性不为空就修改哪个属性
     *
     * @param user 实例对象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean update(User user) {
        return userDao.update(user) == 1;
    }
}

前端控制器:UserController.java
package com.godfrey.easycode.controller;

import com.godfrey.easycode.entity.User;
import com.godfrey.easycode.service.UserService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * description : (User)表控制层
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
@RestController
@RequestMapping("user")
public class UserController {
    /**
     * 服务对象
     */
    @Resource
    private UserService userService;

    /**
     * description : 通过主键查询单条数据
     *
     * @param  id 主键
     * @return 单条数据
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @GetMapping("selectOne")
    public User selectOne(Integer id) {
        return this.userService.queryById(id);
    }
}

Mapper映射文件:UserMapper.xml




    
    
        
        
        
        
    

    
     id, name, age, email 

    
    
        
            name,
        
        
            age,
        
        
            email,
        
    

    
    
        
            #{name},
        
        
            #{age},
        
        
            #{email},
        
    

    
    
        
            name = #{name},
        
        
            age = #{age},
        
        
            email = #{email},
        
    

    
    
        insert into user
        
            
        
        
            
        
    

    
    
        delete from user
        
            id = #{id}
        
    

    
    

    
    

    
    
        update user
        
            
        
        
            id = #{id}
        
    


以上代码完全是生成出来了,从头到尾只需要点几下鼠标,是不是很神奇!


3.我的默认定制模板


entity.java

##引入宏定义
$!define

##使用宏定义设置回调(保存位置与文件后缀)
#save("/entity", ".java")

##使用宏定义设置包后缀
#setPackageSuffix("entity")

##使用全局变量实现默认包导入
$!autoImport
import java.io.Serializable;

##使用宏定义实现类注释信息
#tableComment("实体类")
public class $!{tableInfo.name} implements Serializable {
    private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
    #if(${column.comment})/**
     * ${column.comment}
     */#end

    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end

#foreach($column in $tableInfo.fullColumn)
    ##使用宏定义实现get,set方法
    #getSetMethod($column)
#end

    @Override
    public String toString() {
        return "$!{tableInfo.name}{" +
    #foreach($column in $tableInfo.fullColumn)
            "$!{column.name}=" + $!{column.name} +
    #end
            '}';
    }
}

dao.java

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Dao"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/dao"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}dao;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表数据库访问层
 *
 * @author $!author
 * @since  $!time.currTime()
 */
@Mapper
public interface $!{tableName} {

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 影响行数
     * @author $!author
     * @since  $!time.currTime()
     */
    int insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 删除$!{tableInfo.name}
     *
     * @param  $!pk.name 主键
     * @return 影响行数
     * @author $!author
     * @since  $!time.currTime()
     */
    int deleteById($!pk.shortType $!pk.name);

    /**
     * description : 通过ID查询单条数据
     *
     * @param  $!pk.name 主键
     * @return 实例对象
     * @author $!author
     * @since  $!time.currTime()
     */
    $!{tableInfo.name} queryById($!pk.shortType $!pk.name);

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll();

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 修改$!{tableInfo.name}
     *
     * @param  user 根据$!tool.firstLowerCase($!{tableInfo.name})的主键修改数据
     * @return 影响行数
     * @author $!author
     * @since  $!time.currTime()
     */
    int update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
}

service.java

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Service"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import java.util.List;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表服务接口
 *
 * @author $!author
 * @since  $!time.currTime()
 */
public interface $!{tableName} {

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 删除$!{tableInfo.name}
     *
     * @param  $!pk.name 主键
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean deleteById($!pk.shortType $!pk.name);

    /**
     * description : 查询单条数据
     * @param  $!pk.name 主键
     * @return 实例对象
     * @author $!author
     * @since  $!time.currTime()
     */
    $!{tableInfo.name} queryById($!pk.shortType $!pk.name);

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll();

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 修改数据,哪个属性不为空就修改哪个属性
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
}

serviceImpl.java

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceImpl"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service/impl"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.dao.$!{tableInfo.name}Dao;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

 /**
  * description : $!{tableInfo.comment}($!{tableInfo.name})表服务实现类
  *
  * @author $!author
  * @since  $!time.currTime()
  **/
@Service("$!tool.firstLowerCase($!{tableInfo.name})Service")
public class $!{tableName} implements $!{tableInfo.name}Service {

    @Autowired
    protected $!{tableInfo.name}Dao $!tool.firstLowerCase($!{tableInfo.name})Dao;

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.insert($!tool.firstLowerCase($!{tableInfo.name})) == 1;
    }

    /**
     * description : 删除$!{tableInfo.name}
     *
     * @param  $!pk.name 主键
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean deleteById($!pk.shortType $!pk.name) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.deleteById($!pk.name) == 1;
    }

    /**
     * description : 查询单条数据
     *
     * @param  $!pk.name 主键
     * @return 实例对象
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public $!{tableInfo.name} queryById($!pk.shortType $!pk.name) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryById($!pk.name);
    }

    /**
     * description : 查询全部数据(分页使用MyBatis的插件实现)
     *
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public List<$!{tableInfo.name}> queryAll() {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryAll();
    }

    /**
     * description : 实体作为筛选条件查询数据
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 对象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryAll($!tool.firstLowerCase($!{tableInfo.name}));
    }

    /**
     * description : 修改数据,哪个属性不为空就修改哪个属性
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 实例对象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.update($!tool.firstLowerCase($!{tableInfo.name})) == 1;
    }
}

controller.java

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Controller"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/controller"))
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}controller;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表控制层
 *
 * @author $!author
 * @since  $!time.currTime()
 */
@RestController
@RequestMapping("$!tool.firstLowerCase($tableInfo.name)")
public class $!{tableName} {
    /**
     * 服务对象
     */
    @Resource
    private $!{tableInfo.name}Service $!tool.firstLowerCase($tableInfo.name)Service;

    /**
     * description : 通过主键查询单条数据
     *
     * @param  id 主键
     * @return 单条数据
     * @author $!author
     * @since  $!time.currTime()
     */
    @GetMapping("selectOne")
    public $!{tableInfo.name} selectOne($!pk.shortType id) {
        return this.$!{tool.firstLowerCase($tableInfo.name)}Service.queryById(id);
    }
}

mapper.xml

##引入mybatis支持
$!mybatisSupport

##设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Dao.xml"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mybatis/mapper"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end





    
    
#foreach($column in $tableInfo.fullColumn)
        
#end
    

    
     #allSqlColumn() 

    
    
#foreach($column in $tableInfo.otherColumn)
        
            $!column.obj.name,
        
#end
    

    
    
#foreach($column in $tableInfo.otherColumn)
        
            #{$!column.name},
        
#end
    

    
    
#foreach($column in $tableInfo.otherColumn)
        
            $!column.obj.name = #{$!column.name},
        
#end
    

    
    
        insert into $!{tableInfo.obj.name}
        
            
        
        
            
        
    

    
    
        delete from $!{tableInfo.obj.name}
        
            $!pk.obj.name = #{$!pk.name}
        
    

    
    

    
    

    
    
        update $!{tableInfo.obj.name}
        
            
        
        
            $!pk.obj.name = #{$!pk.name}
        
    


新创建一个分组Lombok,可以在生成实体类的时候使用Lombok注解

MyBatis-Plus入门,看这一篇就足够了_第21张图片,

MyBatis-Plus入门,看这一篇就足够了_第22张图片

实体类层:entity.java

##引入宏定义
$!define

##使用宏定义设置回调(保存位置与文件后缀)
#save("/entity", ".java")

##使用宏定义设置包后缀
#setPackageSuffix("entity")

##使用全局变量实现默认包导入
$!autoImport
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

##使用宏定义实现类注释信息
#tableComment("实体类")
@AllArgsConstructor
@Data
@Builder
public class $!{tableInfo.name} implements Serializable {
    private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
    #if(${column.comment})/**
    * ${column.comment}
    */#end

    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}

多个分组的切换

选择好分组后,点击OK,之后在Datebase视图的数据表右键选择EasyCode生成的时候会让你选择当前分组的模板

,MyBatis-Plus入门,看这一篇就足够了_第23张图片

MyBatis-Plus入门,看这一篇就足够了_第24张图片,

MyBatis-Plus入门,看这一篇就足够了_第25张图片,

MyBatis-Plus入门,看这一篇就足够了_第26张图片.

你可能感兴趣的:(MyBatis-Plus入门,看这一篇就足够了)