Mybatis-Plus(简称MP)是一个 Mybatis 的一个增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。其愿景是成为Mybatis最好的搭档,将开发效率翻倍,由于受到学习研究深入限制,本例只进行Mybatis Plus在Spring Boot环境下的基本应用(如Select、Insert、Update、Delete等基本操作,其中还包括动态生成组合查询与更新的动态SQL语句)。
特性:
无侵入:Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做增强不做改变,引入 Mybatis-Plus 不会对您现有的 Mybatis 构架产生任何影响,而且 MP 支持所有 Mybatis 原生的特性。
依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring
损耗小:启动即会自动注入基本CURD,性能基本无损耗,直接面向对象操作。
预防Sql注入:内置Sql注入剥离器,有效预防Sql注入攻击。
通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。
多种主键策略:支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题。
支持ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作。
支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(P.S. 比 Mybatis 官方的 Generator 更加强大!)。
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )。
支持关键词自动转义:支持数据库关键词(order、key……)自动转义,还可自定义关键词。
内置分页插件:基于Mybatis物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询。
内置性能分析插件:可输出Sql语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询。
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,预防误操作。
1、依赖配置(Spring Boot方式)
pom.xml引入MyBatis依赖类
com.baomidou
mybatisplus-spring-boot-starter
1.0.5
com.baomidou
mybatis-plus
2.1.9
application.yaml配置内容如下:
#mybatis plus配置
mybatis-plus:
#由于本例中采用注解方式编写sql,故而此处可不配置
#mapper-locations: classpath:/mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.szss.admin.model
#枚举扫描配置(本示例未使用到)
#typeEnumsPackage: com.szss.admin.model.domain
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"UUID";
id-type: 0
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 2
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器(由于本例中采用注解方式编写sql,故而不需要刷新mapper.xml文件)
#refresh-mapper: true
#数据库大写下划线转换
capital-mode: true
#序列接口实现类配置,在新的mybatis-plus-boot-starter中不推荐此方式进行配置,推荐自定义bean注入
key-generator: com.baomidou.mybatisplus.incrementer.H2KeyGenerator
#逻辑删除配置(下面3个配置)
logic-delete-value: 1
logic-not-delete-value: 0
sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
# SQL 解析缓存,开启后多租户 @SqlParser 注解生效
sql-parser-cache: true
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
这样我们就完成了MyBatis Plus基本快速开发配置,接下来我们看看具体如何快速进行开发。
2、简单示例
假设我们已存在一张 Role 表,且已有对应的实体类 Role,实现 Role 表的 CRUD 操作我们需要做什么呢?
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.szss.admin.model.domain.RoleDO;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author Allen
* @date 2018/3/7
*
* RoleDO实体数据操作对象
*/
@Mapper
public interface RoleDAO extends BaseMapper {
//其他公共方法!
}
以上就是所需的所有操作,不需要您创建任何XML文件,接下来我们如何使用它基本的CRUD呢?
*角色的CRUD操作代码信息
/**
* 根据角色ID查询角色
*
* @param id 角色ID
* @return 角色信息
*/
RoleDO roleDO = roleDAO.selectById(id);
/**
* 根据查询条件查询角色列表(分页)
*
* @roleParam 查询条件
* @return 角色列表分页信息
*/
Page page = new Page(roleParam.getPi().intValue(), roleParam.getPs().intValue());
//这里会动态根据前台所传入的值自动组合需要查询的字段信息,从而实现动态查询语句
EntityWrapper eWrapper = new EntityWrapper(roleDO);
List roleDOList = roleDAO.selectPage(page,eWrapper);
/**
* 角色新增
*
* @param roleParam 角色信息
* @return 角色信息
*/
roleDAO.insert(roleDO);
/**
* 角色更新(这里mybatis plus的CRUD 操作会自动更新所需要更新的字段动态生成更新语句)
*
* @param roleParam 角色信息
* @return 角色信息
*/
roleDAO.updateById(roleDO);
/**
* 角色删除(如果需要逻辑删除而非物理删除的话,需要结合@TableLogic标签使用,后续会说明)
*
* @param id 角色Id
* @return 删除角色
*/
roleDAO.deleteById(id);
以上是基本的 CRUD 操作,当然可用的 API 远不止这几个,目前最新版本可提供了多达 19 个方法给大家使用,可以极其方便的实现单一、批量、分页等操作,上述中 selectPage即是MP 实现分页的强大操作,而对于EntityWrapper还可以动态组合各种复杂的查询条件各种组合。如上述所见,仅仅需要继承一个 BaseMapper 即可实现大部分单表 CRUD 操作,极大的减少的开发负担。有人也许会质疑:这难道不是通用 Mapper 么?别急,咱们接着往下看。
现有一个需求,我们需要分页查询 User 表中,年龄在18~50之间性别为男且姓名为张三的所有用户,这时候我们该如何实现上述需求呢?
传统做法是 Mapper 中定义一个方法,然后在 Mapper XML 中填写对应的 SELECT 语句或者使用@SelectProvider注解来进行SQL语句代码的硬拼接,且还要集成分页,实现以上一个简单的需求,往往需要我们做很多重复单调的工作,普通的通用 Mapper或@SelectProvider能够解决这类痛点么?答案是肯定的,不能!
用 MP 的方式打开以上需求
// 分页查询 10 条姓名为‘王五’、性别为男,且年龄在18至50之间的用户记录
List userList = userMapper.selectPage(
new Page(1, 10),
new EntityWrapper().eq("name", "王五")
.eq("sex", 0)
.between("age", "18", "50")
);
以上操作,等价于
SELECT *
FROM sys_user
WHERE (name='王五' AND sex=0 AND age BETWEEN '18' AND '50')
LIMIT 0,10
Mybatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者 Condition(与EW类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担,能够有效提高开发效率。关于具体的EntityWrapper与Condition的用法请关注后续更多的文章说明,本例中不进行详细展开叙述。
ActiveRecord 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅,所以我们也在 AR 道路上进行了一定的探索,喜欢大家能够喜欢,也同时欢迎大家反馈意见与建议。
我们如何使用 AR 模式?
直接贴代码观内容:
package com.szss.admin.model.domain;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableLogic;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.mapper.SqlCondition;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* @author Allen
* @date 2018/3/7 角色实体
*/
@Data
@TableName("admin_role")
public class RoleDO extends Model {
/**
* 角色ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 角色名称
*/
@TableField(condition = SqlCondition.LIKE)
private String name;
/**
* 角色描述
*/
private String description;
/**
* 是否启用:0-不可用,1-可用
*/
private Boolean enabled;
/**
* 删除标示:0-未删除,1-已删除
*/
@TableLogic
private Boolean deleted;
/**
* 创建人ID
*/
protected Long creatorId;
/**
* 创建人
*/
protected String creator;
/**
* 创建时间
*/
@SuppressFBWarnings("EI_EXPOSE_REP")
protected Date dateCreated;
/**
* 修改人ID
*/
protected Long modifierId;
/**
* 修改人
*/
protected String modifier;
/**
* 更新时间
*/
@SuppressFBWarnings("EI_EXPOSE_REP")
protected Date lastModified;
/** 指定主键 */
@Override
protected Serializable pkVal() {
return this.id;
}
}
如上所述仅仅需要继承 Model 类且实现主键pkVal指定方法 即可让实体开启 AR 之旅,开启 AR 之路后,又将如何使用它呢?其实比较简单,在上述<角色的CRUD操作代码信息>中角色新增、更新与查询角色列表我们通过roleDAO.selectPage方法进行分页查询,而现在只需要直接通过roleDO.selectPage直接进行查询,具体代码如下所示:
/**
* 查询角色列表(分页)
*
* @param roleParam 角色参数
* @return 查询角色分页列表
*/
public Page selectListPage(ListRoleParam roleParam) {
RoleDO roleDO = new RoleDO();
BeanUtils.copyProperties(roleParam, roleDO);
Page page = new Page((int)roleParam.getPi(), (int)roleParam.getPs());
EntityWrapper eWrapper = new EntityWrapper(roleDO);
// Page roleDOList = roleDAO.selectPage(page, eWrapper);//非AR方式的调用.
Page roleDOList = roleDO.selectPage(page, eWrapper);//这里使用的就是Model提供的AR
return roleDOList;
}
AR 模式提供了一种更加便捷的方式实现 CRUD 操作,其本质还是调用的 Mybatis 对应的方法。
通过以上两个简单示例,我们简单领略了 Mybatis-Plus 的魅力与高效率,可以快速开发代码开发,真正的做到了即开即用。
对于上述RoleDO中的部分注解现就进行说明如下:
@TableName("admin_role") // 注解指定表名
//主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",UUID:"全局唯一ID UUID";
@TableId(type = IdType.AUTO)
@TableField(condition = SqlCondition.LIKE)//在查询时匹配like动态语句
MP支持以下4中主键类型策略,可根据需求自行选用:
值 | 描述 |
---|---|
IdType.AUTO | 数据库ID自增 |
IdType.INPUT | 用户输入ID |
IdType.ID_WORKER | 全局唯一ID,内容为空自动填充(默认配置) |
IdType.UUID | 全局唯一ID,内容为空自动填充 |
上述三个注解是最为基本注解,也较为常用,对于各注解里面的参数详细部分不属于本示例范畴故而不一一详细说明。
通过上述三个注解可以动态生成Insert语句,在插入新增角色时,自动生成Insert into admin_role (name,description,enabled deleted,...) values(...)对应的字段,而自动忽略id字段,因id主键通过@TableId注解为数据库自增类型。
而对于name这样的字段在日常查询中往往是通过like方式来进行匹配的而非精确匹配,所以此处通过@TableField(condition = SqlCondition.LIKE)来实现动态组合查询条件,其应用示例如上<根据查询条件查询角色列表(分页)>selectPage的应用,会根据前台传入的参数自动组合查询语句并进行分页。
其他update操作本示例中通过指定ID字段进行动态语句更新操作,当传入的值不为空时自动组合所需要更新的字段,而where条件即为指定的主键,自动生成update admin_role set name = '王五' where id=1,当然如果想实现某些字段更新成空的情况下,也可通过field-strategy属性配置的方式来进行实现。通过new EntityWrapper
在本例中delete操作并不是真正意义上的物理删除,而是逻辑删除,如果不配置@TableLogic注解的话,则为物理删除,会自动生成delete admin_role where id=1的语句。如yml文件中配置了逻辑删除结合使用@TableLogic注解的话为逻辑删除,自动生成UPDATE admin_role SET deleted=1 WHERE id=1的语句(本例中不删除为0(False),删除为1(Ture),故而logic-delete-value: 1与logic-not-delete-value: 0如是配置)。
注:当配置了@TableLogic注解时在mp自带查询和更新方法的sql后面,追加『逻辑删除字段』=『LogicNotDeleteValue默认值』 删除方法: deleteById()和其他delete方法, 底层SQL调用的是update tbl_xxx set 『逻辑删除字段』=『logicDeleteValue默认值』
至此我们完成了数据库的DML与DQL的基本操作,在不改变现有的框架下,快速启用Mybatis plus的插件,简化操作提高开发效率,极大了解决了编写SQL语句的繁重工作,同时集成分页实现,减少代码量,从而为快速开发做好基础!