1 通用CRUD *MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网:https://mybatis.plus/文档: https://mp.baomidou.com/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习
文档中有的资源我会用 * 表示 ,不会在这里说明
继承baseMapper就可以获取到各种各样的单表操作
baseMapper接口文件
package com.baomidou.mybatisplus.core.mapper;import com.baomidou.mybatisplus.core.conditions.Wrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;import com.baomidou.mybatisplus.core.toolkit.Constants;import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;import org.apache.ibatis.annotations.Param;import java.io.Serializable;import java.util.Collection;import java.util.List;import java.util.Map;public interface baseMapper
这个文档里面包含了springboot的配置以及 xml配置
https://baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
3 条件构造器 *https://baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
实例
QueryWrapper
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法
调用包括:
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的
一些方法等。
总体概括为:
拦截器示例
package cn.itcast.mp.plugins;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import java.util.Properties;@Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})})public class MyInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { //拦截方法,具体业务逻辑编写的位置 return invocation.proceed(); } @Override public Object plugin(Object target) { //创建target对象的代理对象,目的是将当前拦截器加入到该对象中 return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { //属性设置 }}
注入到spring容器
@Beanpublic MyInterceptor myInterceptor(){return new MyInterceptor();}
mybatis-config.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境
SpringBoot配置:
@Beanpublic SqlExplainInterceptor sqlExplainInterceptor(){ SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();List
测试
@Testpublic void testUpdate(){ User user = new User(); user.setAge(20); int result = this.userMapper.update(user, null); System.out.println("result = " + result);}
4.3、性能分析插件性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用。
<?xml version="1.0" encoding="UTF-8" ?>
执行结果
Time:11 ms - ID:cn.itcast.mp.mapper.UserMapper.selectByIdExecute SQL: SELECT id, user_name, password, name, age, email FROM tb_user WHERe id=7
可以看到,执行时间为11ms。如果将maxTime设置为1,那么,该操作会抛出异常。
Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: The SQLexecution time is too large, please optimize !at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:49)at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38)................
4.4、乐观锁插件 *地址
https://baomidou.com/pages/0d93c0/#optimisticlockerinnerinterceptor
5、Sql 注入器 * 我们已经知道,在MP中,通过AbstractSqlInjector将baseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行。
那么,如果我们需要扩充baseMapper中的方法,又该如何实现呢?
下面我们以扩展findAll方法为例进行学习。
package cn.itcast.mp.mapper;import com.baomidou.mybatisplus.core.mapper.baseMapper;import java.util.List;public interface MybaseMapper
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展
package cn.itcast.mp.mapper;import cn.itcast.mp.pojo.User;public interface UserMapper extends MybaseMapper
如果直接继承AbstractSqlInjector的话,原有的baseMapper中的方法将失效,所以我们选择继承DefaultSqlInjector
进行扩展。
package cn.itcast.mp.sqlInjector;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;import java.util.List;public class MySqlInjector extends DefaultSqlInjector { @Override public List getMethodList() { List methodList = super.getMethodList(); methodList.add(new FindAll()); // 再扩充自定义的方法 list.add(new FindAll()); return methodList; }}
5.3、编写FindAllpackage cn.itcast.mp.sqlInjector;import com.baomidou.mybatisplus.core.enums.SqlMethod;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.metadata.TableInfo;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlSource;public class FindAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sqlMethod = "findAll"; String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo); }}
5.4、注册到Spring容器@Beanpublic MySqlInjector mySqlInjector(){return new MySqlInjector();}
5.5、测试@Testpublic void testFindAll(){ List
输入的SQL
[main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Preparing: select * fromtb_user[main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Parameters:[main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] <== Total: 10
6、自动填充功能 * 有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version
等。在MP中提供了这样的功能,可以实现自动填充。
@TableField(fill = FieldFill.INSERT) //插入数据时进行填充private String password;
为password添加自动填充功能,在新增数据时有效。
FieldFill提供了多种模式选择:
public enum FieldFill { DEFAULT, INSERT, UPDATe, INSERT_UPDATE}
6.2、编写MymetaObjectHandlerpackage cn.itcast.mp.handler;import com.baomidou.mybatisplus.core.handlers.metaObjectHandler;import org.apache.ibatis.reflection.metaObject;import org.springframework.stereotype.Component;@Componentpublic class MymetaObjectHandler implements metaObjectHandler { @Override public void insertFill(metaObject metaObject) { Object password = getFieldValByName("password", metaObject); if(null == password){ //字段为空,可以进行填充 setFieldValByName("password", "123456", metaObject); } } @Override public void updateFill(metaObject metaObject) { }}
6.3、测试@Testpublic void testInsert(){ User user = new User(); user.setName("关羽"); user.setUserName("guanyu"); user.setAge(30); user.setEmail("guanyu@itast.cn"); user.setVersion(1); int result = this.userMapper.insert(user); System.out.println("result = " + result);}
7、 逻辑删除 *开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正
的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免
数据被真正的删除。
MP就提供了这样的功能,方便我们使用,接下来我们一起学习下。
7.1、修改表结构为tb_user表增加deleted字段,用于表示数据是否被删除,1代表删除,0代表未删除。
ALTER TABLE `tb_user`ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER`version`;
同时,也修改User实体,增加deleted属性并且添加@TableLogic注解:
@TableLogicprivate Integer deleted;
7.2、配置application.properties:
逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
7.3、测试@Testpublic void testDeleteById(){this.userMapper.deleteById(2L);}
执行的SQL:
[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: UPDATEtb_user SET deleted=1 WHERe id=? AND deleted=0[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 2(Long)[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1
测试查询
@Testpublic void testSelectById(){ User user = this.userMapper.selectById(2L); System.out.println(user);}
执行的sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECTid,user_name,password,name,age,email,version,deleted FROM tb_user WHERe id=? ANDdeleted=0[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Parameters: 2(Long)[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] <== Total: 0
8、 通用枚举 *解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!
8.1、修改表结构ALTER TABLE `tb_user`ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`;
8.2、定义枚举package cn.itcast.mp.enums;import com.baomidou.mybatisplus.core.enums.IEnum;import com.fasterxml.jackson.annotation.JsonValue;public enum SexEnum implements IEnum
枚举包扫描
mybatis-plus.type-enums-package=cn.itcast.mp.enums
8.4、修改实体private SexEnum sex;
8.5 测试@Testpublic void testInsert(){ User user = new User(); user.setName("貂蝉"); user.setUserName("diaochan"); user.setAge(20); user.setEmail("diaochan@itast.cn"); user.setVersion(1); user.setSex(SexEnum.WOMAN); int result = this.userMapper.insert(user); System.out.println("result = " + result);}
sql
[main] [cn.itcast.mp.mapper.UserMapper.insert]-[DEBUG] ==> Preparing: INSERT INTOtb_user ( user_name, password, name, age, email, version, sex ) VALUES ( ?, ?, ?, ?, ?,?, ? )[main] [cn.itcast.mp.mapper.UserMapper.insert]-[DEBUG] ==> Parameters:diaochan(String), 123456(String), 貂蝉(String), 20(Integer), diaochan@itast.cn(String),1(Integer), 2(Integer)[main] [cn.itcast.mp.mapper.UserMapper.insert]-[DEBUG] <== Updates: 1
查询测试
@Testpublic void testSelectById(){ User user = this.userMapper.selectById(2L); System.out.println(user);}
sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECTid,user_name,password,name,age,email,version,deleted,sex FROM tb_user WHERe id=? AND deleted=0[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Parameters: 2(Long)[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] <== Total: 1User(id=2, userName=lisi, password=123456, name=李四, age=30, email=test2@itcast.cn,address=null, version=2, deleted=0, sex=女)
9 代码生成器 * 10.Mybatis整合MP文档: https://mp.baomidou.com/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习
带有 * 的表示 官网里有更详细的资料
[DEBUG] <== Updates: 1
查询测试```java@Testpublic void testSelectById(){ User user = this.userMapper.selectById(2L); System.out.println(user);}
sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECTid,user_name,password,name,age,email,version,deleted,sex FROM tb_user WHERe id=? AND deleted=0[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Parameters: 2(Long)[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] <== Total: 1User(id=2, userName=lisi, password=123456, name=李四, age=30, email=test2@itcast.cn,address=null, version=2, deleted=0, sex=女)
9 代码生成器 * 10.Mybatis整合MP文档: https://mp.baomidou.com/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习
带有 * 的表示 官网里有更详细的资料