mybatis-plus使用小結

mybatis-plus使用小結

前言

今年开始使用mybatis-plus ORM 框架对数据库操作,相比之前使用mybatis,mp 确实能大大提高开发效率,最近刚完成一个小项目,记录一下近期使用。mp是国人写的,官网的资料也很全,基本参考官网的内容摸索就能快速上手使用。mybatis-plus官网

这里只给出要点代码参考.我这里使用的MP的版本是: 3.4.2

一、yaml配置

mybatis-plus的 配置官网参考:使用配置

# mybatis plus 设置
mybatis-plus:
  type-aliases-package: com.zlv11.*.entity
  mapper-locations: classpath:mapper/*.xml
  configuration:
  # 开启执行日志打印
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    # 是否控制台 print mybatis-plus 的 LOGO 这里关闭
    banner: false

二、优雅的查询

Mapper层 继承 BaseMapper 即可获取到通用简单的 增删改查,但是没有批量增,和灵活的根据相应条件进行修改删除操作。因此要使用MP的厉害之处就需要使用 Service CRUD 接口。

下面展示了3中查询方式:从优雅的角度来看,个人偏向使用第二或三种,当然第一种在query条件复用的情况下也能节省代码。也可以指定查询字段剔除不需要的字段,例如表中含有 text或longtext等大字段,比较影响性能,不需要的情况下剔除能提高查询性能。最后2中查询是使用MySQL函数的方式,可以做指定字段忽略大小写查询 SELECT table_id,flow_no,sponsor,create_time FROM appro_flow_main WHERE (sponsor = 'zlv11' AND lower(table_id) LIKE '%staff%')

/**
 * @author lvzb
 * @date 2022/09/07  16:59
 **/
@Slf4j
@SpringBootTest
class FlowMainMapperTest {

    @Resource
    private FlowMainManager flowMainManager;

    @Test
    void test1() {
        // 单条查询 方式一
        QueryWrapper<FlowMain> query = new QueryWrapper<>();
        query.lambda().eq(FlowMain::getFlowNo, "123456").eq(FlowMain::getSponsor, "zlv11");
        FlowMain main1 = flowMainManager.getOne(query);

        // 单条查询 方式二
        FlowMain main2 = flowMainManager.getOne(Wrappers.<FlowMain>lambdaQuery()
                .eq(FlowMain::getFlowNo, "123456")
                .eq(FlowMain::getSponsor, "zlv11"));
        
        // 单条查询 方式三
        FlowMain main3 = flowMainManager.lambdaQuery()
                .eq(FlowMain::getFlowNo, "123456")
                .eq(FlowMain::getSponsor, "zlv11")
                .one();

        // 批量查询,指定字段,不指定默认是全字段查询 apply是使用SQL的函数
        List<FlowMain> flowMainList = flowMainManager.lambdaQuery()
                .eq(FlowMain::getFlowNo, "123456")
                .eq(FlowMain::getSponsor, "zlv11")
                .apply(String.format("find_in_set('%s',approver)", "hlb"))
                .select(FlowMain::getId, FlowMain::getFlowNo, FlowMain::getSponsor, FlowMain::getCreateTime)
                .list();
                
        String tableName = "STaFF";
        // 大小写不敏感 查询
        List<FlowMain> flowMains = flowMainManager.lambdaQuery()
                .eq(FlowMain::getSponsor, "zlv11")
                .apply(StringUtils.isNotBlank(tableName), "lower(table_id) LIKE '%" + tableName.toLowerCase() + "%'")
                .select(FlowMain::getTableId,FlowMain::getFlowNo,FlowMain::getSponsor,FlowMain::getCreateTime)
                .list();
        flowMains.stream().forEach(System.out::println);
    }

三、优雅的更新

mybatis-plus的更新操作也是很优雅,类似查询也有好几种方式。

  • 其中第一种方式,条件可以复用,同时也可以配合MP的一些属性自动填充机制,例如更具阿里的开发规范,表需要含有更新时间字段,这种就可以使用字段自动填充的机制进行处理。
  • 第二第三种方式比较优雅,没有条件复用的情况下建议使用,但是无法使用自动填充机制,然后需要注意末尾的 updata()。
  • 第四种方式末尾是remove(), 则会进行删除操作,如果链中也有各种set(),set()不起作用,也不会报错。
    @Test
    void test2() {
        // 更新方式一: 配合MP的一些属性自动填充机制
        UpdateWrapper<FlowMain> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(FlowMain::getId, 1).eq(FlowMain::getFlowInstanceNo, "aaa");
        FlowMain flowMain = FlowMain.builder().id(1).flowInstanceNo("aaa").updateTime(LocalDateTime.now()).build();
        flowMainManager.update(flowMain, updateWrapper);

        // 更新方式二: 无法使用自动填充机制
        flowMainManager.update(Wrappers.<FlowMain>lambdaUpdate().eq(FlowMain::getId, 1).eq(FlowMain::getFlowInstanceNo, "aaa")
                .set(FlowMain::getSponsor, "zlv11").set(FlowMain::getUpdateTime, LocalDateTime.now()));

        // 更新方式三: 无法使用自动填充机制
        flowMainManager.lambdaUpdate()
                .eq(FlowMain::getId, 1)
                .eq(FlowMain::getFlowInstanceNo, "aaa")
                .set(FlowMain::getSponsor, "zlv11")
                .set(FlowMain::getUpdateTime, LocalDateTime.now())
                .update();

        // 方式四 remove就是删除
        flowMainManager.lambdaUpdate()
                .eq(FlowMain::getId, 1)
                .eq(FlowMain::getFlowInstanceNo, "aaa")
                .set(FlowMain::getSponsor, "zlv11") // set虽然可以设置实际上执行时是不生效的,也不会报错
                .remove();

    }

四、自动填充功能

参考官网使用,需要在实体的字段上加上 @TableField 注解标识 是插入时填充还是插入更新时填充。然后在 自定义元对象处理器接口实现类中配置好即可

Entity

/**
 *
 * @author lvzb
 * @date 2022/08/09  10:40
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("appro_flow_main")
public class FlowMain implements Serializable {

    @TableId(type = IdType.AUTO)
    private Integer id;
    private String flowInstanceNo;
    private String flowInstanceName;
    private String flowNo;
    private String approStatus;
    private String submitInfo;
    private String tableId;
    private String sponsor;
    private Integer initiDate;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

}

自定义实现类 MyMetaObjectHandler

这里给所有的 createTime ,updateTime字段定义插入时填充 当前日期, 更新时 对updateTime字段填充 当前日期。注意这里配置的字段,只有在entity中使用了注解 @TableField 修饰后,然后对应的新增和修改才会生效。

/**
 *
 * @author lvzb
 * @date 2022/08/20  21:28
 **/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class);
        this.strictInsertFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class);
    }

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

五、分页查询

分页查询是很常见的

配置分页插件

这个要更具你使用版本来,官网版本要求:3.4.0 版本以上 是如下配置

@Configuration
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}

老版本是这种配置

@Configuration
public class MybatisPlusConfig {
    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

查询

普通的查询

 @Test
    void test3() {
        Page<FlowMain> page = new Page<>(1,10);
        flowMainManager.lambdaQuery().eq(FlowMain::getFlowNo,"123456").page(page);
        List<FlowMain> records = page.getRecords();
    }

复杂分页查询,传入xml内,确保第一个参数是 Page即可,执行后,查询数据会放到传入的Page 对象的 records 属性中

/**
 * @author lvzb
 * @date 2022/08/09  19:01
 **/
@Mapper
public interface FlowMainMapper extends BaseMapper<FlowMain> {

    /**
     * 待办获取 分页
     *
     * @param page    分页参数
     * @param request 请求参数
     * @return Page<ApproNodeModel>
     */
    Page<ApproNodeModel> selectToDoPage(Page<ApproNodeModel> page,
                                         @Param("request") ToDoRequest request);

    /**
     * 已办获取 分页
     *
     * @param page    分页参数
     * @param request 请求参数
     * @return Page<ApproNodeModel>
     */
    Page<ApproNodeModel> selectDonePage(Page<ApproNodeModel> page,
                                        @Param("request") DoneRequest request);

}
    @Test
    void test() {
        String approver = "zlv11";
        DoneRequest doneRequest = new DoneRequest();
        doneRequest.setUserNo(approver);
        Page<ApproNodeModel> page1 = new Page<>(1, 10);
        flowMainMapper.selectDonePage(page1, doneRequest);
        page1.getRecords().stream().forEach(System.out::println);
    }

控制台打印如下内容

2022-11-18 15:12:38.299  WARN 87776 --- [           main] c.a.d.b.dao.mapper.FlowMainMapperTest    : >>> 10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值