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();
}




















 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值