当前位置: 首页 > article >正文

Mybatis-Plus新花样(二)

多种插件

Mybatis-plus给我们提供了各种各样的插件,方便我们快捷开发。

一. 插件配置

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 配置分页插件, 针对 MySQL
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 阻止全表更新全表删除
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁
        return interceptor;
    }
}

二. 分页插件(PaginationInnerInterceptor)

分页查询是自带Limit关键字

三. 防止全表更新和删除插件(BlockAttackInnerInterceptor)

这里仅模拟删除所有。全表更新是一样的。

四. 乐观锁插件(OptimisticLockerInnerInterceptor)

乐观锁插件会在我们设置version的值后,只更新与其version值对应的一次。修改一次后会自动+1

数据库字段实体类都需要加上version字段。记得初始化为0

模拟并发场景,假设两个线程同时修改user的信息

@Test
void testVersion() throws InterruptedException {
    User user1 = new User();
    user1.setId(1);

    User user2 = new User();
    user2.setId(1);

    Integer version = user1.selectById().getVersion();
    CountDownLatch countDownLatch = new CountDownLatch(2);
    new Thread(()->{
        user1.setUsername("666");
        user1.setVersion(version);
        boolean flag = user1.updateById();
        System.out.println("666是否执行:" + flag);
        countDownLatch.countDown();
    },"t1").start();


    new Thread(()->{
        user2.setUsername("777");
        user2.setVersion(version);
        boolean flag = user2.updateById();
        System.out.println("777是否执行:" + flag);
        countDownLatch.countDown();
    },"t2").start();

    countDownLatch.await();
}

结果为

只有一个完成修改。

自动填充数据

MyBatis-Plus 提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。

一. 实现MetaObjectHandler接口

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject,"create_time", LocalDateTime.class, LocalDateTime.now());
        this.setFieldValByName("update_time", LocalDateTime.now(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject,"update_time", LocalDateTime.class, LocalDateTime.now());
    }
}

实体类添加@TableField注解

@Data
@Builder
@TableName("`user`")
@AllArgsConstructor
@RequiredArgsConstructor
public class User extends Model<User> {
    @TableId(type = IdType.AUTO)
    private Integer id;

    private String username;

    private String password;

    private Boolean enabled;
    @Version
    private Integer version;
    @TableLogic(value = "false",delval = "true")
    private Boolean is_deleted;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime create_time;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime update_time;
}

二.测试

  1. 插入一条数据
@Test
void testAdd() {
    User user = User.builder()
            .username("999")
            .password(encoder.encode("123456"))
            .enabled(true)
            .build();
    user.insert();
}

测试结果

  1. 更新数据
@Test
void testUpdate(){
    User user = User.builder()
            .id(6)
            .username("Coffee")
            .build();
    user.updateById();
}

SQL注入器

MyBatis-Plus 提供了灵活的机制来注入自定义的 SQL 方法,这通过 sqlInjector 全局配置实现。通过实现 ISqlInjector 接口或继承 AbstractSqlInjector 抽象类,你可以注入自定义的通用方法到 MyBatis 容器中。

一. 注册自定义方法

定义类继承AbstractMethod,重写方法

public class DeleteAll extends AbstractMethod {
=
    protected DeleteAll(String methodName) {
        super(methodName);
    }
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "update " + tableInfo.getTableName() + " set is_deleted = true";
        String methodName = "deleteAll";
        //1. 创建sqlSource, 通过sqlSource可以获取sql
        SqlSource sqlSource = this.languageDriver.createSqlSource(configuration, sql, modelClass);
        //2. 添加到mappedStatement中
        return this.addUpdateMappedStatement(mapperClass,Boolean.class,methodName, sqlSource);
    }
}

二. 创建sql注入器

将刚刚自定义的方法注入到注入器中.

继承AbstactSqlInjector类,重写getMethodList方法。

注意: 如果是实现AbstractSqlInjector类,将会导致Mybatis-plus自带的所有方法全部失效


@Component
public class MySglInject extends AbstractSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methods = new ArrayList<>();
        methods.add(new DeleteAll("deleteAll"));
        return methods;
    }
}

要想仅仅只是多出我们的自定义方法,需要继承DefaultSqlInject类,并且获取到父类的MethodList集合

@Component
public class MySglInject extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);

        methodList.add(new DeleteAll("deleteAll"));
        return methodList;
    }
}

三. Mapper层定义方法

在mapper层写入我们自定义的方法,必须和自定义的方法名保持一致。


@Mapper
public interface UserMapper extends BaseMapper<User> {

    void deleteAll();
}

四. 测试

@Test
void testDeleteALLSQLInject(){
    userMapper.deleteAll();
}




















 


http://www.kler.cn/news/328619.html

相关文章:

  • Robot Operating System——带有协方差矩阵的三维空间中的位姿(位置和方向)
  • 基于 Seq2Seq 的中英文翻译项目(pytorch)
  • 番外篇 | 复现AC-YOLOv5,进行自动化织物缺陷检测
  • Mybatis 9种动态 sql 标签使用
  • 基于深度学习的任务序列中的快速适应
  • 基于微信小程序的宿舍报修系统的设计与实现(lw+演示+源码+运行)
  • 正交阵的概念、性质与应用
  • 激光切割机适用材质有哪些
  • 证件照换底色免费
  • Nginx基础详解4(location模块、nginx跨域问题的解决、nginx防盗链的设计原理及应用、nginx模块化解剖)
  • Vue.js 组件开发
  • 【数据库】 MongoDB 查看当前用户的角色和权限
  • C++八股进阶
  • 【API安全】crAPI靶场全解
  • (void*) 是啥意思
  • 【Vue】为什么 Vue 不使用 React 的分片更新?
  • 重置linux后vscode无法再次使用ssh连接
  • C# HttpClient请求URL重定向后丢失Authorization认证头
  • 基于RustDesk自建远程桌面服务
  • 0基础学前端 day9--css布局
  • UI设计师面试整理-团队合作与沟通能力
  • 深度学习·wandb
  • 自然语言处理问答系统技术
  • html5 + css3(下)
  • STL容器适配器
  • OpenCV 形态学相关函数详解及用法示例
  • 字符串逆序
  • 滚雪球学MySQL[3.3讲]:MySQL复杂查询详解:CASE语句、自连接与视图管理
  • OpenCV视频I/O(11)视频采集类VideoCapture之设置视频捕获设备的属性函数 set()的使用
  • Go语言入门:掌握基础语法与核心概念