前言
mybatis plus是一个mybatis的增强工具,在其基础上只做增强不做改变。作为开发中常见的第三方组件,学习并应用在项目中可以节省开发时间,提高开发效率。
官方文档地址:MyBatis-Plus (baomidou.com)
一、特性
1.1损耗小
自动注入基本CRUD,性能无损耗,直接面向对象操作(通过BaseMaper<约定的泛型>);
1.2支持lambda表达式
通过lambda表达式的形式,方便编写各类查询条件,无需担心字段出错;
1.3支持主键自动生成
内含分布式唯一ID生成器-Squence,可自行配置主键;
1.4支持ActiveRecord模式
实体类只需继承Model类即可进行CRUD操作;
1.5支持分页插件
基于mybatis物理分页,配置好插件后自动将数据分页;
二、快速入门
2.1创建数据库
2.1.1建表
代码语言:javascript复制DROP TABLE IF EXISTS user;CREATE TABLE user(
id BIGINT() NOT NULL COMMENT '主键ID',
name VARCHAR() NULL DEFAULT NULL COMMENT '姓名',
age INT() NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR() NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id)
);
2.1.2初始化项目
- 导入依赖(尽量不要与mybatis一起导入)
- 配置依赖
- 编写代码
- 拓展技术能力
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
2.1.3连接数据库
代码语言:javascript复制#mysql配置#数据库用户名spring.datasource.username=root#登录密码spring.datasource.password=password123#JDBC地址、编码、安全连接spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8#数据库驱动spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2.2编写代码
2.2.1实体类
代码语言:javascript复制@Data@AllArgsConstructor@NoArgsConstructorpublic class User { //用户id
private Long id; //用户名
private String name; //年龄
private Integer age; //邮箱
private String email;
}
2.2.2mapper文件
代码语言:javascript复制@Mapper@Repository//该接口继承BaseMapper类所有方法public interface UserMapper extends BaseMapper<User> {
}
2.2.3逻辑实现层
代码语言:javascript复制 @Autowired
private UserMapper userMapper; //创建条件构造器
QueryWrapper<User> wrapper = new QueryWrapper<>();
userMapper.selectList(wrapper);
2.3日志配置
代码语言:javascript复制#mybatis-plus日志配置,默认控制台输出日志,properties文件mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2.4CRUD扩展
2.4.1插入操作(insert)
代码语言:javascript复制 void insert(){ User user = new User();
user.setName("Alex");
user.setAge();
user.setEmail("4353435@qq.com"); //受影响的行数
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user);
}
主键生成策略
实体类声明数据库表名,同时设置主键id为自增。
代码语言:javascript复制//数据库表名@TableName("user")public class User implements Serializable { //用户id,主键自增
@TableId(value = "id",type = IdType.AUTO)
private Long id;
}
2.4.2更新操作(update)
代码语言:javascript复制 //更新操作
@Test
void updateTest(){ User user = new User();
user.setId(3L);
user.setName("docker&K8s"); //操作结果条数
int i = userMapper.updateById(user);
System.out.println(i);
}
时间自动填充策略
方式一(数据库级别):不推荐使用
在数据库中新建字段并设置为操作的当前时间,且需要在实体类同步属性:
从而达到自动填充时间的。
代码语言:javascript复制 private Date createTime; private Date updateTime;
方式二(代码级别):
- 在实体类属性加上对应注解,自动填充时间字段:
@TableField(fill = FieldFill.INSERT)
private Date createTime; @TableField(fill = FieldFill.UPDATE)
private Date updateTime;
- 代码逻辑中新建时间对象获取当前时间(推荐使用):
user.setUpdateTime(new Date());
2.4.3乐观锁处理
在面试中经常会提及悲观锁、乐观锁的概念,其实这两个概念非常简单。
乐观锁
乐观锁顾名思义十分乐观,它总是认为不会出现问题,无论干什么都不会去上锁。如果出现问题,就再更新值去测试。
悲观锁
悲观锁顾名思义十分悲观,它总是认为会出现问题,无论干什么都会去上锁,然后再去操作。
乐观锁机制
- 取出记录时,获取当前version
- 更新时带上该version
- 执行更新时,set version = newVersion where version = oldVersion
- 若version不对,则更新失败
乐观锁:、先去查询获得版本号version = --A线程update user set name = "zhuzhiqiang",version = version where id = and version =
代码语言:javascript复制若B线程抢先完成,这时version = ,导致线程A修改失败--B线程update user set name = "zhuzhiqiang",version = version where id = and version =
测试mybatisPlus的乐观锁插件
1、在数据库表中添加version字段:
2、实体类添加对应属性,并添加@Version注解:
代码语言:javascript复制 //乐观锁字段(注解)
@Version
private Integer version;
3、注册组件:
代码语言:javascript复制@EnableTransactionManagement //事务管理注解@Configurationpublic class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){ return new OptimisticLockerInterceptor();
}
}
2.4.4分页查询处理(本质上还是执行limit)
使用步骤
配置拦截器组件(配置类中):
直接使用Page对象即可:
2.4.5删除操作
逻辑删除
逻辑删除指的是在数据库中没有被删除,而是通过一个变量来使其失效:deleted = 0 -> deleted = 1
数据库表中增加字段:
实体类中添加对应属性:
properties配置:
测试删除(本质上是一个更新操作):
注:若执行了逻辑删除,那么再次查询该条数据时,会在select语句中自动拼接deleted=0,即查询不到该条语句。
2.4.6条件构造器Wrapper
按照复杂条件进行查询,本质上等价于使用复杂sql进行查询。
源码分析:
测试使用:
复杂条件的SQL查询
- like模糊查询
public
void
testLike(){
QueryWrapper<User> wrapper = new
QueryWrapper<>(); //相当于where语句,
wrapper //表示name字段中 不包含e的数据
.notLike("name","e") //右查询,以t开头的email字段数据
.likeRight("email", "t");
}
三、高级用法
3.1基本概念
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
3.2创建工具类
代码语言:javascript复制public class AutoCodeTool { public static void main(String[] args) { //构建代码自动生成器对象
AutoGenerator autoCode = new AutoGenerator(); //全局配置生效
autoCode.setGlobalConfig(gc); //数据源生效
autoCode.setDataSource(dsc); //包配置生效
autoCode.setPackageInfo(packageConfig); //其它策略生效
autoCode.setStrategy(strategyConfig); //执行代码生成器
autoCode.execute();
}
}
3.3全局配置
代码语言:javascript复制//1、全局配置GlobalConfig gc = new GlobalConfig();//输出目录,将自动生成的代码生成在以下路径中String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath "/src/main/java");//设置作者信息gc.setAuthor("Created by zhuzqc");//生成代码后不打开文件管理器gc.setOpen(false);//是否覆盖原来生成的代码gc.setFileOverride(false);//主键类型gc.setIdType(IdType.ID_WORKER);//时间类型gc.setDateType(DateType.ONLY_DATE);//配置swagger文档gc.setSwagger2(true);
3.4设置数据源
代码语言:javascript复制//2、设置数据源DataSourceConfig dsc = new DataSourceConfig();//数据源具体配置dsc.setUrl("jdbc:mysql://localhost:3306/mubatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("password123");
dsc.setDbType(DbType.MYSQL);
3.5包的配置
代码语言:javascript复制//3、包的配置PackageConfig packageConfig = new PackageConfig();//生成包路径packageConfig.setParent("com.dcone");//生成模块名packageConfig.setModuleName("common");//生成entitypackageConfig.setEntity("pojo");//生成mapperpackageConfig.setMapper("dao");//生成servicepackageConfig.setService("service");//生成controllerpackageConfig.setController("controller");
3.6其它策略
代码语言:javascript复制//4、其它策略StrategyConfig strategyConfig = new StrategyConfig();//设置需要映射的数据库表strategyConfig.setInclude("user");//驼峰命名strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//设置LombokstrategyConfig.setEntityLombokModel(true);//RESTFUL风格strategyConfig.setRestControllerStyle(true);//逻辑删除strategyConfig.setLogicDeleteFieldName("deleted");//自动填充配置(创建和修改时间)TableFill gmtCreate = new TableFill("gmt_create_time", FieldFill.INSERT);TableFill gmtModified = new TableFill("gmt_modified_time", FieldFill.INSERT_UPDATE);
autoCode.setStrategy(strategyConfig);//作为列表元素添加自动填充策略ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategyConfig.setTableFillList(tableFills);//乐观锁配置strategyConfig.setVersionFieldName("version");//访问URL下划线风格strategyConfig.setControllerMappingHyphenStyle(true);
四、总结
4.1优点
- 通过少量配置即可实现单表大部分 CRUD 操作(将简单查询封装),更有强大的条件构造器,满足各类使用需求;
- 采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎;
- 支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。
4.2缺点
- 对数据访问层DAO的上层入侵太强,入侵到service、甚至controller,将层次结构耦合起来;
- 数据查询代码复杂,最终SQL过程黑盒,不利于业务性优化,不利于排查问题;
- 一旦项目跃迁到微服务,其难以在复杂高性能大规模服务上应用。