简介
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
- 无侵入:Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做增强不做改变,引入 Mybatis-Plus 不会对您现有的 Mybatis 构架产生任何影响,而且 MP 支持所有 Mybatis 原生的特性
- 依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 预防Sql注入:内置 Sql 注入剥离器,有效预防Sql注入攻击
- 通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 多种主键策略:支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题
- 支持热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
- 支持ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作
- 支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(P.S. 比 Mybatis 官方的 Generator 更加强大!)
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 支持关键词自动转义:支持数据库关键词(order、key......)自动转义,还可自定义关键词
- 内置分页插件:基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,预防误操作
架构原理
下面就是springboot与MyBatis-Plus集成,spring和MyBatis-Plus(这个参考官网:http://mp.baomidou.com/)。
- pom.xml引入
<dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>最新版本号</version> </dependency> </dependencies> <!-- 如果mapper.xml是放在src/main/java目录下,需配置以下--> <build> <resources> <resource> <directory>src/main/java</directory> <filtering>false</filtering> <includes> <include>**/mapper/*.xml</include> </includes> </resource> </resources> </build>
-
application.yml配置文件
mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml # 如果是放在resource目录 classpath:/mapper/*Mapper.xml mapper-locations: classpath:/mapper/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.yourpackage.*.entity global-config: #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; id-type: 3 #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: 2 #驼峰下划线转换 db-column-underline: true #mp2.3+ 全局表前缀 mp_ #table-prefix: mp_ #刷新mapper 调试神器 #refresh-mapper: true #数据库大写下划线转换 #capital-mode: true # Sequence序列接口实现类配置 key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator #逻辑删除配置(下面3个配置) logic-delete-value: 1 logic-not-delete-value: 0 sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector #自定义填充策略接口实现 meta-object-handler: com.baomidou.springboot.MyMetaObjectHandler configuration: #配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId) map-underscore-to-camel-case: true cache-enabled: false #配置JdbcTypeForNull, oracle数据库必须配置 jdbc-type-for-null: 'null'
-
Java Configuration配置更多配置参考
@Configuration @MapperScan("com.yourpackage.*.mapper*") public class MybatisPlusConfig { /* * 分页插件,自动识别数据库类型 * 多租户,请参考官网【插件扩展】 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } /* * oracle数据库配置JdbcTypeForNull * 参考:https://gitee.com/baomidou/mybatisplus-boot-starter/issues/IHS8X 不需要这样配置了,参考 yml: mybatis-plus: confuguration dbc-type-for-null: 'null' @Bean public ConfigurationCustomizer configurationCustomizer(){ return new MybatisPlusCustomizers(); } class MybatisPlusCustomizers implements ConfigurationCustomizer { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.setJdbcTypeForNull(JdbcType.NULL); } } */ }
配置:
@EnableTransactionManagement
@Configuration
public class ConfigurationPlugin {
/**
* 分页插件
* @return
*/
@Bean
public PaginationInterceptor create(){
return new PaginationInterceptor();
}
/**
* 拦截删除全表的操作--setStopProceed这个要设置成true,
SQL 执行分析拦截器【 目前只支持 MYSQL-5.6.3 以上版本 】,
作用是分析 处理 DELETE UPDATE 语句, 防止小白或者恶意 delete update 全表操作!
* @return
*/
@Bean
public SqlExplainInterceptor createSqlExplainInterceptor(){
SqlExplainInterceptor interceptor = new SqlExplainInterceptor();
interceptor.setStopProceed(true);
return interceptor;
}
/**
* 性能分析插件
* @return
*/
//@Profile({"dev","test","pr"})
@Bean
public PerformanceInterceptor createPerformanceInterceptor(){
PerformanceInterceptor interceptor = new PerformanceInterceptor();
interceptor.setMaxTime(100);
interceptor.setFormat(true);
return interceptor;
}
/**
* 乐观锁插件,这个也要在数据库添加一个字段来当version版本记录,
也需要在属性里上面添加一个注解@version
* @return
*/
@Bean
public OptimisticLockerInterceptor createOptimisticLockerInterceptor(){
return new OptimisticLockerInterceptor ();
}
/**
* 这个是自己添加方法
* @return
*/
@Bean
public MySqlInjector createMySqlInjector(){
return new MySqlInjector();
}
/**
* 公共字段自动填充
* @return
*/
@Bean
public MyMetaObjectHandler createMyMetaObjectHandler(){
return new MyMetaObjectHandler();
}
}
/**
*下面是我自定义的--公共字段自动填充的方案
*/
public class MyMetaObjectHandler extends MetaObjectHandler{
@Override
public void insertFill(MetaObject metaObject) {
System.out.println("在插入是如果name的值为空时,可以插入值");
Object name = getFieldValByName("lastName", metaObject);
System.out.println(name);
if(name==null){
setFieldValByName("lastName", "wangbin", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
/**
*下面试自己的方法--写的自动注入sql的方式
*/
public interface DeptMapper extends BaseMapper<Dept>{
int deleteAll();
}
public class MySqlInjector extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
Class<?> modelClass, TableInfo table) {
//注入的SQL语句
String sql = "delete from " +table.getTableName();
//注入的方法名 一定要与EmployeeMapper接口中的方法名一致
String method = "deleteAll" ;
//构造SqlSource对象
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
//构造一个删除的MappedStatement
this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
核心功能:
1、代码生成器可以参考官网http://mp.baomidou.com/#/generate-code:
下面是我写的代码示例:
/**
* 代码生成 示例代码
*/
@Test
public void testGenerator() {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
config.setActiveRecord(true) // 是否支持AR模式
.setAuthor("wang") // 作者
.setOutputDir("E:\\bauduyunpan\\shang\\尚硅谷MyBatisPlus视频教程\\MyBatisPlus\\代码\\mp03\\src\\main\\java") // 生成路径
.setFileOverride(true) // 文件覆盖
.setIdType(IdType.AUTO) // 主键策略
.setServiceName("%sService") // 设置生成的service接口的名字的首字母是否为I
// IEmployeeService
.setBaseResultMap(true)
.setBaseColumnList(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
dsConfig.setDbType(DbType.MYSQL) // 设置数据库类型
.setDriverName("com.mysql.jdbc.Driver")
.setUrl("jdbc:mysql://localhost:3306/mp")
.setUsername("root")
.setPassword("root");
//3. 策略配置
StrategyConfig stConfig = new StrategyConfig();
stConfig.setCapitalMode(true) //全局大写命名
.setDbColumnUnderline(true) // 指定表名 字段名是否使用下划线
.setNaming(NamingStrategy.underline_to_camel) // 数据库表映射到实体的命名策略
.setTablePrefix("tbl_")
.setInclude("tbl_employee"); // 生成的表
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("com.jrj.mp")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("beans")
.setXml("mapper");
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 执行
ag.execute();
}
2、通用的CURD
简单介绍
TODO
实体无注解化设置,表字段如下规则,主键叫 id 可无注解大写小如下规则。
1、驼峰命名 【 无需处理 】
2、全局配置: 下划线命名 dbColumnUnderline 设置 true , 大写 isCapitalMode 设置 true
注解说明
表名注解
@TableName
- com.baomidou.mybatisplus.annotations.TableName
值 | 描述 |
---|---|
value | 表名( 默认空 ) |
resultMap | xml 字段映射 resultMap ID |
主键注解
@TableId
- com.baomidou.mybatisplus.annotations.TableId
值 | 描述 |
---|---|
value | 字段值(驼峰命名方式,该值可无) |
type | 主键 ID 策略类型( 默认 INPUT ,全局开启的是 ID_WORKER ) |
暂不支持组合主键
字段注解
@TableField
- com.baomidou.mybatisplus.annotations.TableField
值 | 描述 |
---|---|
value | 字段值(驼峰命名方式,该值可无) |
update | 预处理 set 字段自定义注入 |
condition | 预处理 WHERE 实体条件自定义运算规则 |
el | 详看注释说明 |
exist | 是否为数据库表字段( 默认 true 存在,false 不存在 ) |
strategy | 字段验证 ( 默认 非 null 判断,查看 com.baomidou.mybatisplus.enums.FieldStrategy ) |
fill | 字段填充标记 ( FieldFill, 配合自动填充使用 ) |
- TableField 注解新增属性
update
预处理 set 字段自定义注入例如:@TableField(.. , update="%s+1") 其中 %s 会填充为字段 输出 SQL 为:update 表 set 字段=字段+1 where ...
例如:@TableField(.. , update="now()") 使用数据库时间 输出 SQL 为:update 表 set 字段=now() where ...
-
TableField 注解新增属性
condition
预处理 WHERE 实体条件自定义运算规则@TableField(condition = SqlCondition.LIKE) private String name; 输出 SQL 为:select 表 where name LIKE CONCAT('%',值,'%')
-
字段填充策略 FieldFill
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入填充字段 |
UPDATE | 更新填充字段 |
INSERT_UPDATE | 插入和更新填充字段 |
序列主键策略 注解
@KeySequence
- com.baomidou.mybatisplus.annotations.KeySequence
值 | 描述 |
---|---|
value | 序列名 |
clazz | id的类型 |
乐观锁标记注解
@Version
- com.baomidou.mybatisplus.annotations.Version
排除非表字段、查看文档常见问题部分!
3、条件构造器
实体包装器,用于处理 sql 拼接,排序,实体参数查询等!
补充说明: 使用的是数据库字段,不是Java属性!
实体包装器 EntityWrapper 继承 Wrapper
简单示例
- 翻页查询
public Page<T> selectPage(Page<T> page, EntityWrapper<T> entityWrapper) {
if (null != entityWrapper) {
entityWrapper.orderBy(page.getOrderByField(), page.isAsc());
}
page.setRecords(baseMapper.selectPage(page, entityWrapper));
return page;
}
- 拼接 sql 方式 一
@Test
public void testTSQL11() {
/*
* 实体带查询使用方法 输出看结果
*/
EntityWrapper<User> ew = new EntityWrapper<User>();
ew.setEntity(new User(1));
ew.where("user_name={0}", "'zhangsan'").and("id=1")
.orNew("user_status={0}", "0").or("status=1")
.notLike("user_nickname", "notvalue")
.andNew("new=xx").like("hhh", "ddd")
.andNew("pwd=11").isNotNull("n1,n2").isNull("n3")
.groupBy("x1").groupBy("x2,x3")
.having("x1=11").having("x3=433")
.orderBy("dd").orderBy("d1,d2");
System.out.println(ew.getSqlSegment());
}
- 拼接 sql 方式 二
int buyCount = selectCount(Condition.create()
.setSqlSelect("sum(quantity)")
.isNull("order_id")
.eq("user_id", 1)
.eq("type", 1)
.in("status", new Integer[]{0, 1})
.eq("product_id", 1)
.between("created_time", startDate, currentDate)
.eq("weal", 1));
- 自定义 SQL 方法如何使用 Wrapper
mapper java 接口方法
List<User> selectMyPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
mapper xml 定义
<select id="selectMyPage" resultType="User">
SELECT * FROM user
<where>
${ew.sqlSegment}
</where>
</select>
关于 ${ew.sqlSegment} 使用了 $ 不要误以为就会被 sql 注入,请放心使用 mp 内部对 wrapper 进行了字符转义处理!
条件参数说明
查询方式 | 说明 |
---|---|
setSqlSelect | 设置 SELECT 查询字段 |
where | WHERE 语句,拼接 + WHERE 条件 |
and | AND 语句,拼接 + AND 字段=值 |
andNew | AND 语句,拼接 + AND (字段=值) |
or | OR 语句,拼接 + OR 字段=值 |
orNew | OR 语句,拼接 + OR (字段=值) |
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderAsc | ASC 排序 ORDER BY |
orderDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last("LIMIT 1") |
注意! xxNew 都是另起 ( ... )
括号包裹。
下面是我写的一些代码:
https://github.com/zhangyuxiangwang/springboot2.git
4、插件扩展参考官网:
http://mp.baomidou.com/#/page-plugin