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 baseMapper2 mybatis-plus配置 *extends Mapper { int insert(T entity); int deleteById(Serializable id); int deleteById(T entity); int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap); int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper); int deleteBatchIds(@Param(Constants.COLLECTION) Collection> idList); int updateById(@Param(Constants.ENTITY) T entity); int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper); T selectById(Serializable id); List selectBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList); List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap); default T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper) { List ts = this.selectList(queryWrapper); if (CollectionUtils.isNotEmpty(ts)) { if (ts.size() != 1) { throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records"); } return ts.get(0); } return null; } default boolean exists(Wrapper queryWrapper) { Long count = this.selectCount(queryWrapper); return null != count && count > 0; } Long selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper); List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); List
这个文档里面包含了springboot的配置以及 xml配置
https://baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE3 条件构造器 *
https://baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
实例
QueryWrapper4. 插件 4.1、mybatis的插件机制wrapper = new QueryWrapper<>(); //SELECT id,name,age FROM tb_user WHERe name = ? OR age = ? wrapper.eq("name", "李四") .or() .eq("age", 24) .select("id", "name", "age"); List users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); }
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法
调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)ParameterHandler (getParameterObject, setParameters)ResultSetHandler (handleResultSets, handleOutputParameters)StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的
一些方法等。
总体概括为:
- 拦截执行器的方法拦截参数的处理拦截结果集的处理拦截Sql语法构建的处理
拦截器示例
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容器
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
mybatis-config.xml配置
4.2 执行分析插件
在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境
SpringBoot配置:
@Bean
public SqlExplainInterceptor sqlExplainInterceptor(){
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List sqlParserList = new ArrayList<>();
// 攻击 SQL 阻断解析器、加入解析链
sqlParserList.add(new BlockAttackSqlParser());
sqlExplainInterceptor.setSqlParserList(sqlParserList);
return sqlExplainInterceptor;
}
测试
@Test
public void testUpdate(){
User user = new User();
user.setAge(20);
int result = this.userMapper.update(user, null);
System.out.println("result = " + result);
}
4.3、性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用。
执行结果
Time:11 ms - ID:cn.itcast.mp.mapper.UserMapper.selectById
Execute 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 SQL execution 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/#optimisticlockerinnerinterceptor5. 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 MybaseMapperextends baseMapper { List findAll(); }
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展
package cn.itcast.mp.mapper; import cn.itcast.mp.pojo.User; public interface UserMapper extends MybaseMapper5.2、编写MySqlInjector{ User findById(Long id); }
如果直接继承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、编写FindAll
package 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容器
@Bean
public MySqlInjector mySqlInjector(){
return new MySqlInjector();
}
5.5、测试
@Test
public void testFindAll(){
List users = this.userMapper.findAll();
for (User user : users) {
System.out.println(user);
}
}
输入的SQL
[main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Preparing: select * from tb_user [main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Parameters: [main] [cn.itcast.mp.mapper.UserMapper.findAll]-[DEBUG] <== Total: 106. 自动填充功能 *
有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version
等。在MP中提供了这样的功能,可以实现自动填充。
@TableField(fill = FieldFill.INSERT) //插入数据时进行填充 private String password;
为password添加自动填充功能,在新增数据时有效。
FieldFill提供了多种模式选择:
public enum FieldFill {
DEFAULT,
INSERT,
UPDATe,
INSERT_UPDATE
}
6.2、编写MymetaObjectHandler
package cn.itcast.mp.handler;
import com.baomidou.mybatisplus.core.handlers.metaObjectHandler;
import org.apache.ibatis.reflection.metaObject;
import org.springframework.stereotype.Component;
@Component
public 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、测试
@Test
public 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注解:
@TableLogic private 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=07.3、测试
@Test
public void testDeleteById(){
this.userMapper.deleteById(2L);
}
执行的SQL:
[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: UPDATE tb_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
测试查询
@Test
public void testSelectById(){
User user = this.userMapper.selectById(2L);
System.out.println(user);
}
执行的sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email,version,deleted 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: 08、 通用枚举 *
解决了繁琐的配置,让 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 IEnum8.3、配置{ MAN(1,"男"), WOMAN(2,"女"); private int value; private String desc; SexEnum(int value, String desc) { this.value = value; this.desc = desc; } @Override public Integer getValue() { return this.value; } @Override public String toString() { return this.desc; } }
枚举包扫描
mybatis-plus.type-enums-package=cn.itcast.mp.enums8.4、修改实体
private SexEnum sex;8.5 测试
@Test
public 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 INTO tb_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
查询测试
@Test
public void testSelectById(){
User user = this.userMapper.selectById(2L);
System.out.println(user);
}
sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,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: 1 User(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
@Test
public void testSelectById(){
User user = this.userMapper.selectById(2L);
System.out.println(user);
}
sql
[main] [cn.itcast.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,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: 1 User(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/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习
带有 * 的表示 官网里有更详细的资料



