MyBatis-Plus
MyBatis-Plus
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
CRUD扩展
添加依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency></dependencies>
配置
#数据库连接配置spring.datasource.username=rootspring.datasource.password=123456spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#配置日志mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl#配置逻辑删除mybatis-plus.global-config.db-config.logic-delete-value=1mybatis-plus.global-config.db-config.logic-not-delete-value=0
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹:
package com.yrz;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan("com.yrz.mapper")@SpringBootApplicationpublic class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); }}
UserMapper
package com.yrz.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.yrz.pojo.User;import org.springframework.stereotype.Repository;@Repository //代表持久层public interface UserMapper extends BaseMapper<User> {}
User
package com.yrz.pojo;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableLogic;import com.baomidou.mybatisplus.annotation.Version;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructorpublic class User { @TableId(type = IdType.INPUT) private Long id; private String name; private Integer age; private String email; @Version //代表这是乐观锁 private Integer version; @TableLogic //逻辑删除 private Integer deleted;}
MyBatisPlusConfig配置类
package com.yrz.config;import com.baomidou.mybatisplus.core.injector.ISqlInjector;import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;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;@MapperScan("com.yrz.mapper")@EnableTransactionManagement@Configurationpublic class MyBatisPlusConfig { //配置乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } //配置分页插件 @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } //配置逻辑删除组件 @Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); }}
测试类
package com.yrz;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.yrz.mapper.UserMapper;import com.yrz.pojo.User;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.sql.SQLOutput;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;@SpringBootTestclass MybatisPlusApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } //插入测试 @Test public void testInsert(){ User user = new User(); user.setName("xxx"); user.setAge(3); user.setEmail("123@qq.com"); user.setId(8L); int result = userMapper.insert(user); System.out.println(user); System.out.println(result); } //更新测试 @Test public void testUpdate(){ User user = new User(); user.setId(6L); user.setName("yrz"); user.setAge(18); user.setEmail("123@qq.com"); int i = userMapper.updateById(user); System.out.println(i); } //测试乐观锁成功 @Test public void testOptimisticLocker(){ User user = userMapper.selectById(1); user.setName("lwh"); user.setEmail("456@qq.com"); userMapper.updateById(user); } //测试乐观锁失败 @Test public void testOptimisticLocker2(){ //线程1 User user = userMapper.selectById(1); user.setName("lwh1"); user.setEmail("456@qq.com"); //线程2 User user2 = userMapper.selectById(1); user2.setName("lwh2"); user2.setEmail("456@qq.com"); userMapper.updateById(user2); userMapper.updateById(user); } //查询测试 @Test public void testSelectById(){ User user = userMapper.selectById(6); System.out.println(user); } //批量查询 @Test public void testSelectBatchId(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); } //条件查询 map @Test public void testSelectBatchIds(){ HashMap<String, Object> map = new HashMap<>(); map.put("name","yrz"); map.put("age", 18); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); } //分页查询测试 @Test public void testPage(){ Page<User> page = new Page<>(1, 5); userMapper.selectPage(page, null); page.getRecords().forEach(System.out::println); System.out.println(page.getTotal()); } //删除测试 @Test public void testDeleteById(){ userMapper.deleteById(8L); }}
性能分析插件
#设置开发环境spring.profiles.active=dev
导入插件
//SQL执行效率插件 性能分析插件 @Bean @Profile({"dev","test"})// 设置 dev test 环境开启 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setFormat(true);//格式化语句 performanceInterceptor.setMaxTime(5);//执行时间超过多少秒会抛出异常 return performanceInterceptor; }
测试查询
@Testvoid contextLoads() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println);}
条件构造器
Wrapper(十分重要)
package com.yrz;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.yrz.mapper.UserMapper;import com.yrz.pojo.User;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class WrapperTest { @Autowired private UserMapper userMapper; @Test void test1() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper .isNotNull("name") .isNotNull("email") .ge("age", 12); //ge大于等于;le小于等于 gt大于;lt小于 userMapper.selectList(wrapper).forEach(System.out::println); } @Test void test2() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name", "yrz"); userMapper.selectList(wrapper).forEach(System.out::println); } @Test void test3() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.between("age", 20,30); // 区间查询 System.out.println(userMapper.selectCount(wrapper)); } //模糊查询 @Test void test4() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper .notLike("name", "y") .likeRight("email", "t"); userMapper.selectMaps(wrapper).forEach(System.out::println); } @Test void test5() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("id", "select id from user where id<3"); userMapper.selectObjs(wrapper).forEach(System.out::println); } @Test void test6() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("id"); //wrapper.orderByAsc("id"); 升序排序 userMapper.selectList(wrapper).forEach(System.out::println); }}
代码自动生成器
package com.yrz;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.generator.config.DataSourceConfig;import com.baomidou.mybatisplus.generator.config.GlobalConfig;import com.baomidou.mybatisplus.generator.AutoGenerator;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;//代码自动生成器public class CodeGenerator { public static void main(String[] args) { //需要构建一个代码自动生成器对象 AutoGenerator mpg = new AutoGenerator(); //策略配置 //1、全局配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir(projectPath + "/src/main/java"); gc.setAuthor("YRZ"); gc.setOpen(false); gc.setFileOverride(false); //是否覆盖 gc.setServiceName("%sService"); //去Service的I前缀 gc.setIdType(IdType.ID_WORKER); gc.setDateType(DateType.ONLY_DATE); gc.setSwagger2(true); mpg.setGlobalConfig(gc); //2、设置数据源 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("123456"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); //3、包的配置 PackageConfig pc = new PackageConfig(); pc.setModuleName("blog"); pc.setParent("com"); pc.setEntity("entity"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("controller"); mpg.setPackageInfo(pc); //4、策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user"); //设置要映射的表名 strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); //自动lombok strategy.setRestControllerStyle(true); strategy.setLogicDeleteFieldName("delete"); strategy.setVersionFieldName("version"); //乐观锁 strategy.setControllerMappingHyphenStyle(true); mpg.setStrategy(strategy); mpg.execute(); //执行 }}