MyBatis-Plus整合SpringBoot 快速上手,值得收藏!!!

MyBatis-Plus 是一个为了简化开发效率而生的 MyBatis 增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。其整合到 Spring Boot 项目中,可以让开发过程更加便捷。

一、引入依赖


com.baomidou

mybatis-plus-boot-starter

3.5.5

二、在application.properties中配置日志打印

# mybatis日志

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

三、代码案例

(1)实体类

package com.example.entity;

import com.baomidou.mybatisplus.annotation.*;

import lombok.*;

import java.io.Serializable;

import java.util.Date;

@Data

public class User implements Serializable {

/** 主键 */

@TableId(type = IdType.ID_WORKER) // mybatis-plus默认使用IdType.ID_WORKER 雪花算法 Long类型作为id,根据主键类型选择IdType

private Long id;

/** 名称 */

private String name;

/** 年龄 */

private Integer age;

/** 邮箱 */

private String email;

/** 创建时间 */

@TableField(fill = FieldFill.INSERT) // 插入的时候自动填充该字段的值

private Date createTime;

/** 修改时间 */

@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和修改的时候自动填充该字段的值

private Date updateTime;

@TableField(fill = FieldFill.INSERT) // 插入的时候自动填充该字段的值

@Version // 乐观锁版本

private Integer version;

}

/**

mybatis-plus功能:

1、默认使用雪花算法生成主键

2、支持字段值自动填充

*/

(2)配置类

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration

@MapperScan(value = "com.example.mapper")

@EnableTransactionManagement

public class MybatisPlusConfig {

/**

* 乐观锁插件

* @return OptimisticLockerInterceptor

*/

@Bean

public OptimisticLockerInterceptor optimisticLockerInterceptor() {

return new OptimisticLockerInterceptor();

}

/**

* 分页插件

* @return PaginationInterceptor

*/

@Bean

public PaginationInterceptor paginationInterceptor() {

return new PaginationInterceptor();

}

/**

* 逻辑删除时用到

* @return ISqlInjector

*/

@Bean

public ISqlInjector sqlInjector() {

return new LogicSqlInjector();

}

}

(3)元对象处理类

package com.example.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;

import lombok.extern.slf4j.Slf4j;

import org.apache.ibatis.reflection.MetaObject;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

import java.time.ZoneId;

import java.util.Date;

@Component

@Slf4j

public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { // 实现元对象处理器接口

// 获取当前日期

private Date getCurrentDateTime() {

return Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());

}

// 插入元对象字段填充(用于插入时对公共字段的填充)

@Override

public void insertFill(MetaObject metaObject) {

log.info("插入元对象字段填充开始...");

// this.setFieldValByName(属性名称,默认值,metaObject); // 默认值类型 对应 实体类属性类型

this.setFieldValByName("createTime", getCurrentDateTime(), metaObject);

this.setFieldValByName("updateTime", getCurrentDateTime(), metaObject);

this.setFieldValByName("version", 1, metaObject);

log.info("插入元对象字段填充完成...");

}

// 更新元对象字段填充(用于更新时对公共字段的填充)

@Override

public void updateFill(MetaObject metaObject) {

log.info("更新元对象字段填充开始...");

this.setFieldValByName("updateTime", getCurrentDateTime(), metaObject);

log.info("更新元对象字段填充完成...");

}

}

(4)测试类

package com.example;

import com.baomidou.mybatisplus.core.conditions.Wrapper;

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.example.entity.User;

import com.example.mapper.MybatisPlusMapper;

import com.example.util.IdWorker;

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.*;

@RunWith(SpringRunner.class)

@SpringBootTest

public class MybatisPlusTest {

// 逆向生成的类

@Autowired

private MybatisPlusMapper mybatisPlusMapper;

// 网上能找到该类

@Autowired

private IdWorker idWorker;

@Test

public void insertTest() {

User user = new User();

user.setId(idWorker.nextId());

user.setName("xxxxx");

user.setAge(18);

user.setEmail("xxx@qq.com");

int result = mybatisPlusMapper.insert(user);

System.out.println("result = " + result);

System.out.println("id = " + user.getId());

System.out.println(user);

}

@Test

public void updateTest() {

// 需要先查出该对象

User user = mybatisPlusMapper.selectById(1449705947919306752L);

user.setName("小哆啦");

user.setUpdateTime(null);

// 再进行修改操作才会对版本号version进行修改

mybatisPlusMapper.updateById(user);

}

@Test

public void selectTest() {

System.out.println("------------111------------");

User user = mybatisPlusMapper.selectById(1449705947919306752L);

Optional.ofNullable(user).ifPresent(System.out::println);

System.out.println("------------222------------");

List users = mybatisPlusMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L, 4L, 666L));

users.forEach(System.out::println);

Map map = new HashMap<>();

map.put("age", 18);

System.out.println("------------333------------");

List users2 = mybatisPlusMapper.selectByMap(map);

users2.forEach(System.out::println);

QueryWrapper userWrapper = new QueryWrapper<>();

userWrapper.eq("name", "Jack");

userWrapper.isNull("create_time"); // column 这里填的是数据库中的字段名称

System.out.println("------------444------------");

List users3 = mybatisPlusMapper.selectList(userWrapper);

users3.forEach(System.out::println);

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.isNull("create_time");

IPage userIPage = new Page<>(2, 3);

System.out.println("------------555------------");

mybatisPlusMapper.selectPage(userIPage, wrapper);

userIPage.getRecords().forEach(System.out::println);

System.out.println("当前页:" + userIPage.getCurrent());

System.out.println("每页数据条数:" + userIPage.getSize());

System.out.println("总页数:" + userIPage.getPages());

System.out.println("总数据条数:" + userIPage.getTotal());

}

@Test

public void deleteTest() {

// 可以是直接删除一条数据,也可以是逻辑删除,需要看具体配置

mybatisPlusMapper.deleteById(1449654351730593792L);

}

}

/**

1、使用乐观锁需要修改版本号,引入插件后,每一次修改数据版本号都会加1(需要先将数据查出来版本号才会更改)

2、使用Mybatis-plus进行分页查询时,需要将"分页插件"注入容器当中

3、删除时比较特殊,请往下看

*/

四、使用乐观锁

1、乐观锁需要版本号,在数据库中添加 "版本号" 字段;

2、在实体类中添加 "版本号" 属性,并加上 "@version" 注解;

3、将OptimisticLockerInterceptor类注入容器中,该类会对版本号version进行自增操作;

4、代码实际操作,需要先查出该对象,再进行修改操作才会对版本号进行修改(见上述测试类中的updateTest()方法)。

五、字段值自动填充

1、在字段上添加相应注解,如:

@TableField(fill = FieldFill.INSERT) // 插入的时候自动填充该字段的值

@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和修改的时候自动填充该字段的值

2、自定义一个类,实现元对象处理器接口"MetaObjectHandler",重写"insertFill"和"updateFill"方法,并将该类注入容器中

六、物理删除和逻辑删除

// 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

// 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

@Test

public void deleteTest() {

// 可以是直接删除一条数据,也可以是逻辑删除,需要看具体配置

mybatisPlusMapper.deleteById(1449654351730593792L);

}

1、如上代码,当不做任何配置时,会直接进行"物理删除";

2、若要实现"逻辑删除",需如下配置:

(1)在数据库中添加一个字段"deleted";

(2)在实体类中添加一个属性"deleted",并添加相应注解;

// value - 删除前的状态,delval - 删除后的状态

// 表示逻辑删除,加上该注解后,删除语句就会变成更新语句

@TableLogic(value = "0", delval = "1")

// @TableLogic

private Integer deleted;

(3)向容器中注入 "ISqlInjector" 类(逻辑删除插件)

/**

若使用 @TableLogic 而不是 @TableLogic(value = "0", delval = "1") 时,

此时可以在application.properties文件中配置逻辑删除的状态,也可以达到逻辑删除的效果,如下:

# 逻辑删除状态

mybatis-plus.global-config.db-config.logic-delete-value=1

mybatis-plus.global-config.db-config.logic-not-delete-value=0

*/

/**

测试删除方法后分析打印的sql语句,是一条update

注意:被删除数据的 deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作,如下日志

==>  Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0

==> Parameters: 1449654351730593792(Long)

<==    Updates: 0

*/

七、统一返回的json时间格式

默认情况下json时间格式带有时区,并且是世界标准时间,和我们的时间差了八个小时。

可以在"application.properties"文件中进行配置,优化Date类型字段输出格式。

# 返回json的全局时间格式

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

spring.jackson.time-zone=GMT+8

八、SQL 执行性能分析插件(可选)

1、将SQL执行性能分析插件"PerformanceInterceptor"注入容器中

@Configuration

@MapperScan(value = "com.example.mapper")

@EnableTransactionManagement

public class TeacherConfig {

/**

* SQL 执行性能分析插件

* 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长

*/

@Bean

@Profile({"dev","test"})// 设置 dev test 环境开启

public PerformanceInterceptor performanceInterceptor() {

PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();

performanceInterceptor.setMaxTime(100);//ms,超过此处设置的ms则sql不执行

performanceInterceptor.setFormat(true);

return performanceInterceptor;

}

}

2、在application.properties文件中指定开发环境

spring.profiles.active=dev

/**

开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长

*/

九、MyBatis-Plus代码生成器

package com.example;

import com.baomidou.mybatisplus.annotation.DbType;

import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.generator.AutoGenerator;

import com.baomidou.mybatisplus.generator.config.DataSourceConfig;

import com.baomidou.mybatisplus.generator.config.GlobalConfig;

import com.baomidou.mybatisplus.generator.config.PackageConfig;

import com.baomidou.mybatisplus.generator.config.StrategyConfig;

import com.baomidou.mybatisplus.generator.config.rules.DateType;

import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import org.junit.Test;

public class CodeGenerator {

@Test

public void run() {

// 1、创建代码生成器

AutoGenerator mpg = new AutoGenerator();

// 2、全局配置

GlobalConfig gc = new GlobalConfig();

String projectPath = System.getProperty("user.dir");

gc.setOutputDir(projectPath + "/src/main/java");

gc.setAuthor("author");

gc.setOpen(false); // 生成后是否打开资源管理器

gc.setFileOverride(true); // 重新生成时文件是否覆盖

gc.setServiceName("%sService");    // 去掉Service接口的首字母I

gc.setIdType(IdType.ID_WORKER); // 主键策略

gc.setDateType(DateType.ONLY_DATE); // 定义生成的实体类中日期类型

gc.setSwagger2(true); // 开启Swagger2模式

        mpg.setGlobalConfig(gc);

// 3、数据源配置

DataSourceConfig dsc = new DataSourceConfig();

dsc.setUrl("jdbc:mysql://localhost:3306/database_name");

dsc.setDriverName("com.mysql.cj.jdbc.Driver");

dsc.setUsername("root");

dsc.setPassword("123456");

dsc.setDbType(DbType.MYSQL);

mpg.setDataSource(dsc);

// 4、包配置

PackageConfig pc = new PackageConfig();

pc.setModuleName("module-xxx"); // 模块名

pc.setParent("com.example");

pc.setController("controller");

pc.setEntity("entity");

pc.setService("service");

pc.setMapper("mapper");

mpg.setPackageInfo(pc);

// 5、策略配置

StrategyConfig strategy = new StrategyConfig();

strategy.setInclude("t_user"); // 根据哪张表生成

strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库表映射到实体的命名策略

strategy.setTablePrefix(pc.getModuleName() + "_"); // 生成实体时去掉表前缀

strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 数据库表字段映射到实体的命名策略

strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

strategy.setRestControllerStyle(true); // restful api风格控制器

strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符

        mpg.setStrategy(strategy);

// 6、执行

mpg.execute();

}

}

/**

放到test包下,修改一些基本配置后,直接运行run()方法即可

*/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容