简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的加强工具,在 MyBatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。
官网地址:https://mp.baomidou.com/
愿景
咱们的愿景是成为 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
达梦数据库、虚谷数据库、人大金仓数据库
疾速指南
咱们将通过一个简略的 Demo 来论述 MyBatis-Plus 的弱小性能,在此之前,咱们假如您曾经:
领有 Java 开发环境以及相应 IDE
相熟 Spring Boot
相熟 Maven
应用第三方组件:
1、导入对应的依赖
2、钻研依赖如何配置
3、代码如何编写
4、进步扩大技术的能力
步骤
1、创立数据库 mybatis_plus
现有一张 User
其对应的数据库 Schema 脚本如下:
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)
);
-- 实在开发中,version(乐观锁),deleted(逻辑删除)、gmt_create、gem_mo
其对应的数据库 Data 脚本如下:
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2、导入相应的依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis-plus 是本人开发的,非官方的!-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
阐明:咱们应用 mybatis-plus 能够节俭咱们大量的代码,尽量不要同时导入 mybatis 和 mybatis-plus!版本的差别!
3、连贯数据库
# mysql 5 驱动不同 com.mysql.jsbc.Driver
# mysql 8 驱动不同 com.mysql.cj.jsbc.Driver、须要减少时区的配置
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
4、编写代码
pojo–>dao–>(连贯 mybatis,配置 mapper.xml 文件)–>service-controller (传统形式)
应用 mybatis-plus 之后
* pojo
* dao 接口(不必写 mapper.xml 文件)* 应用
编写实体类 User.java(此处应用了 Lombok 简化代码)
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
编写 Mapper 类 UserMapper.java
// 在对应的 Mapper 上继承根本的类 baseMapper
public interface UserMapper extends BaseMapper<User> {
// 所有的 CRUD 曾经编写实现
// 不须要像以前的配置一些 xml
}
在 Spring Boot 启动类中增加 @MapperScan 注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.mapper")// 扫描 mapper 文件夹
public class Application {public static void main(String[] args) {SpringApplication.run(QuickStartApplication.class, args);
}
}
增加测试类,进行功能测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {System.out.println(("----- selectAll method test ------"));
// 参数是一个 Wrapper,条件构造器,这里先不必 填 null
// 查问所有的用户
List<User> userList = userMapper.selectList(null);
Assert.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
UserMapper 中的 selectList() 办法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件
控制台输入:
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
残缺的代码示例请移步:Spring Boot 疾速启动示例 [Spring MVC 疾速启动示例]
5、小结
通过以上几个简略的步骤,咱们就实现了 User 表的 CRUD 性能,甚至连 XML 文件都不必编写!
从以上步骤中,咱们能够看到集成 MyBatis-Plus 十分的简略,只须要引入 starter 工程,并配置 mapper 扫描门路即可。
但 MyBatis-Plus 的弱小远不止这些性能,想要具体理解 MyBatis-Plus 的弱小性能?那就持续往下看吧!
配置日志
咱们所用的 sql 当初是不可见的,咱们心愿晓得他是怎么执行的,所以咱们必须要查看日志!
# 配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdouImpl
CRUD 扩大
Insert 插入
// 插入一条记录
int insert(T entity);
参数阐明
@Test
public void testInsert() {System.out.println(("----- selectAll method test ------"));
User user = new User();
user.setName=("shuishui");
user.setAge(3);
user.setEmail("12434141@qq.com");
userMapper.insert(user);
}
数据库插入的 id 为全局默认的 id(ID_WORKER)
主键生成策略
分布式系统惟一 id 生成
雪花算法
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:应用一个 64 bit 的 long 型的数字作为全局惟一 id。在分布式系统中的利用非常宽泛,且 ID 引入了工夫戳,基本上放弃自增的。
这 64 个 bit 中,其中 1 个 bit 是不必的,而后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。
https://blog.csdn.net/lq18050…
主键自增
咱们须要配置主键自增
1、实体类字段上 @TableId(type =IdType.AUTO)
2、数据库字段肯定要是自增的
其余的码源详解
更新操作
// 依据 whereEntity 条件,更新记录
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
// 依据 ID 批改
int updateById(@Param(Constants.ENTITY) T entity);
参数阐明
举例测试
主动填充
创立工夫、批改工夫!这些个操作一遍都是自动化实现,咱们不心愿手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create\gmt_modified 简直所有的表都要配置上!而且须要自动化
形式一:数据库级别
在表中新增字段 create_time、update_time(默认 CURRENT_TIMESIAMP)
形式二:代码级别
实体类上的属性须要减少注解 ==@TableField==
乐观锁
面试中常常会问到乐观锁,乐观锁
乐观锁:顾名思义非常乐观,它总是被认为不会呈现问题,无论干什么都不去上锁!如果呈现了问题,再次更新测试
乐观锁:顾名思义非常乐观,它总是呈现问题,无论干什么都会上锁!再去操作!
乐观锁实现形式
取出记录是,获取以后 version
更新时,带上这个 version
执行更新事,set version=newVersion where version =oldVersion
如果 version 不对,就更新失败
测试乐观锁
1、表中创立乐观锁字段 version 默认值为 1
2、同步实体类
@Version // 乐观锁 Version 注解
private Integer version;
3、注册组件(config 包下)
springboot:
spring xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
特地阐明:
反对的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
仅反对 updateById(id) 与 update(entity, wrapper) 办法
在 update(entity, wrapper) 办法下, wrapper 不能复用!!!
测试一下:
查问操作
// 依据 ID 查问
T selectById(Serializable id);
// 依据 entity 条件,查问一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查问(依据 ID 批量查问)List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 依据 entity 条件,查问全副记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查问(依据 columnMap 条件)List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 依据 Wrapper 条件,查问全副记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 依据 Wrapper 条件,查问全副记录。留神:只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 依据 entity 条件,查问全副记录(并翻页)IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 依据 Wrapper 条件,查问全副记录(并翻页)IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 依据 Wrapper 条件,查问总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
参数阐明
实例测试
分页查问
分页在网站应用的非常多
1、原始的 limit 进行分页
2、pageHelper 第三方插件
3、Mybatis-Plus 中也内置了分页插件!
如何应用
1、配置拦截器组件即可
2、写测试
删除
// 依据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(依据 ID 批量删除)int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 依据 ID 删除
int deleteById(Serializable id);
// 依据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
参数阐明
测试删除:
在工作中会遇到逻辑删除
逻辑删除
物理删除:从数据库中间接移出
逻辑删除:在数据库中没有被移出,而是通过一个变量来让他生效!deleted=0 ==>deleted =1(生效)
SpringBoot 配置形式:
application.yml 退出配置 (如果你的默认值和 mp 默认的一样, 该配置可无):
注册 Bean(3.1.1 开始不再须要这一步):
实体类字段上加上 @TableLogic 注解
@TableLogic
private Integer deleted;
成果: 应用 mp 自带办法删除和查找都会附带逻辑删除性能 (本人写的 xml 不会)
example
删除时 update user set deleted=1 where id =1 and deleted=0
查找时 select * from user where deleted=0
全局逻辑删除: 3.3.0 开始反对
如果公司代码比拟标准,比方对立了全局都是 flag 为逻辑删除字段。
应用此配置则不须要在实体类上增加 @TableLogic。
但如果实体类上有 @TableLogic 则以实体上的为准,疏忽全局。即先查找注解再查找全局,都没有则此表没有逻辑删除。
附件阐明
逻辑删除是为了不便数据恢复和爱护数据自身价值等等的一种计划,但理论就是删除。
如果你须要再查出来就不应应用逻辑删除,而是以一个状态去示意。
如:员工到职,账号被锁定等都应该是一个状态字段,此种场景不应应用逻辑删除。
若确需查找删除数据,如老板须要查看历史所有数据的统计汇总信息,请独自手写 sql。
以上的 CRUD 操作都必须要把握
性能更新插件
咱们在平时的开发中,会遇到一些慢 sql。测试!druid…
作用:性能剖析拦截器,用于输入每条 SQL 语句及执行工夫
MP 也提供性能剖析插件,如果超过这和工夫就会进行运行
1、导入插件
//Spring boot 形式
@EnableTransactionManagement
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
/**
* SQL 执行效率插件
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);// ms 设置 sql 执行的最大工夫,如果超过就进行
performanceInterceptor.setFormat(true);
return new PerformanceInterceptor();}
}
记得在 SpringBoot 配置环境为 dev 或者 test 环境!
2、测试应用
留神!参数阐明:
参数:maxTime SQL 执行最大时长,超过主动进行运行,有助于发现问题。
参数:format SQL SQL 是否格式化,默认 false。
该插件只用于开发环境,不倡议生产环境应用。
条件结构器
非常重要:Wrapper
咱们写一些简单的 sql 能够用它来实现
现做几个实例看看:
更多的办法都在官网文档里
代码主动生成器
dao、pojo、conrtroller、service 主动生成
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 能够疾速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的晋升了开发效率。
package com.kuang;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
// 代码主动生成器
public class KuangCode {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("狂神说");
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/kuang_community? 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.kuang");
pc.setEntity("entity");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("blog_tags","course","links","sys_settings","user_record","user_say"); // 设置要映射的表名
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// 主动 lombok
strategy.setEntityLombokModel(true);
strategy.setLogicDeleteFieldName("deleted");
// 主动填充配置
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategy.setTableFillList(tableFills);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true);
// localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute();
// 执行
}
}