栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis-Plus

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis-Plus

Mybatis-Plus

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网:https://mybatis.plus/

文档: https://mp.baomidou.com/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习

文档中有的资源我会用 * 表示 ,不会在这里说明

1 通用CRUD *

继承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 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 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> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);

    
    List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);

    
    

> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper); } 2 mybatis-plus配置 *

这个文档里面包含了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 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);
}
4. 插件 4.1、mybatis的插件机制

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/#optimisticlockerinnerinterceptor
5. Sql 注入器 *

我们已经知道,在MP中,通过AbstractSqlInjector将baseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行。
那么,如果我们需要扩充baseMapper中的方法,又该如何实现呢?
下面我们以扩展findAll方法为例进行学习。

5.1、编写MybaseMapper
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.baseMapper;
import java.util.List;
public interface MybaseMapper extends baseMapper {
	List findAll();
}

其他的Mapper都可以继承该Mapper,这样实现了统一的扩展

package cn.itcast.mp.mapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends MybaseMapper {
	User findById(Long id);
}
5.2、编写MySqlInjector

如果直接继承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: 10

6. 自动填充功能 *

有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version
等。在MP中提供了这样的功能,可以实现自动填充。

6.1、添加@TableField注解
@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=0
7.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: 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 {
    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;
    }
}

8.3、配置

枚举包扫描

mybatis-plus.type-enums-package=cn.itcast.mp.enums
8.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/ (点击上面指南中的快速入门)如果需要更多了解 可进入这个官网进行学习

带有 * 的表示 官网里有更详细的资料

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号