像mybatis-plus一样自定义封装BaseMapper方法

今天刷视频的时候看到说判断是否存在使用select 1 from table where *** limit 1这种语句要比,select count 好。所以我看一下mybatis-plus的BaseMapper中的exists方法,发现也是用的select count来判断的

default boolean exists(Wrapper<T> queryWrapper) {
    Long count = this.selectCount(queryWrapper);
    return null != count && count > 0L;
}

好吧,我们自己来写一个吧。

一、首先写一个接口继承BaseMapper,添加一个select1limit1(Wrapper)方法如下:

package com.chhuang.core.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;

/**
 * @ClassName InterfaceMapper
 * @Description Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
 * @Author Darren Huang
 * @Date 2022/11/23 22:56
 * @Version 1.0
 */
public interface InterfaceMapper<T> extends BaseMapper<T> {
    /**
     * 根据 Wrapper 条件,判断是否存在记录,存在返回1,不存在为null
     *
     * @param queryWrapper 实体对象封装操作类
     * @return 是否存在记录
     */
    Integer select1Limit1(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,判断是否存在记录, 存在true,不存在false
     * @param queryWrapper
     * @return
     */
    default boolean exists(Wrapper<T> queryWrapper){
        if(select1Limit1(queryWrapper)==null)
            return false;
        else
            return true;
    }
}

注意:一定要加"@Param(Constants.WRAPPER)",不然运行时会报找不到ew的异常。

二、接下来,学习mybatis-plus的原码,写一下select1limi1的方法类和sql语句的枚举。

package com.chhuang.core.method;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

/**
 * @ClassName IsExist
 * @Description 根据条件判断是否存在
 * @Author Darren Huang
 * @Date 2022/11/23 23:26
 * @Version 1.0
 */
public class Select1Limit1 extends AbstractMethod {

    public Select1Limit1() {
        super(ChSqlMethod.SELECT1_LIMIT1.getMethod());
    }

    /**
     * @param name 方法名
     * @since 3.5.0
     */
    public Select1Limit1(String name) {
        super(name);
    }

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        ChSqlMethod sqlMethod = ChSqlMethod.SELECT1_LIMIT1;
        String sql = String.format(sqlMethod.getSql(), sqlFirst(), tableInfo.getTableName(),
                sqlWhereEntityWrapper(true, tableInfo), sqlComment());
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Integer.class);
    }

    public String getMethod(ChSqlMethod sqlMethod) {
        return StringUtils.isBlank(methodName) ? sqlMethod.getMethod() : this.methodName;
    }
}
package com.chhuang.core.method;
/**
 * @ClassName ChSqlMethod
 * @Description 支持sql方法
 * @Author Darren Huang
 * @Date 2022/11/23 23:28
 * @Version 1.0
 */

public enum ChSqlMethod {

    SELECT1_LIMIT1("select1Limit1", "查询是否存在满足条件记录", "<script>%s SELECT 1 FROM %s %s limit 1 %s\n</script>");

    private final String method;
    private final String desc;
    private final String sql;

    ChSqlMethod(String method, String desc, String sql) {
        this.method = method;
        this.desc = desc;
        this.sql = sql;
    }

    public String getMethod() {
        return method;
    }

    public String getDesc() {
        return desc;
    }

    public String getSql() {
        return sql;
    }
}

当然可以不用这么麻烦可以直接把sql写到Select1limi1类里去,这里是为了学习一下mybatis-plus。

三、现在就需要自己写一个sql注入器了,不然mapper里的select1limit1方法也不知道自己的实现是Select1limi1这个方法。

package com.chhuang.core.injector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.methods.*;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.chhuang.core.method.Select1Limit1;

import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * @ClassName ChSqlInjector
 * @Description 实现SqlInjector
 * @Author Darren Huang
 * @Date 2022/11/24 0:31
 * @Version 1.0
 */
public class ChSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new Select1Limit1());
        return methodList;

//        Stream.Builder<AbstractMethod> builder = Stream.<AbstractMethod>builder()
//                .add(new Select1Limit1());
//        return builder.build().collect(toList());
    }
}

四、现在需要把sql注入器,添加到springboot的配置中,这样就可以在springboot项目中使用自己定义的接口InterfaceMapper了。

package com.chhuang.config;

import com.chhuang.core.injector.ChSqlInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName SqlInjectorConfig
 * @Description 配置sql注入器
 * @Author Darren Huang
 * @Date 2022/11/24 0:40
 * @Version 1.0
 */

@Configuration
public class SqlInjectorConfig {

    @Bean
    public ChSqlInjector sqlInjector(){
        return new ChSqlInjector();
    }
}

五、最后,我们再自定义一个service接口,我这里叫InterfaceService,把自己数据库表实例对象对应的的mapper实现BaseMapper改成实现InterfaceMapper,把对应的service接口改为实现我们自定义的InterfaceService接口。

package com.chhuang.core.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * @ClassName InterfaceService
 * @Description 又一个顶级 Service
 * @Author Darren Huang
 * @Date 2022/11/24 0:10
 * @Version 1.0
 */
public interface InterfaceService<T> extends IService<T> {

    /**
     * 根据 Wrapper 条件,判断是否存在记录, 存在true,不存在false
     * @param queryWrapper
     * @return
     */
    default boolean exists(Wrapper<T> queryWrapper){
        return getBaseMapper().exists(queryWrapper);
    }
}

上面都是需要封装的代码,比如可以放到叫core的module中,下面自己的业务代码:

package com.chhuang.mapper;

import com.chhuang.core.mapper.InterfaceMapper;
import com.chhuang.model.ChUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * @ClassName ChUserMapper
 * @Description 表数据库访问层(ChUserMapper)
 * @Author Darren Huang
 * @Date 2022-11-19 01:12:42
 * @Version 1.0
 */
@Mapper
@Repository
public interface ChUserMapper extends InterfaceMapper<ChUser> {

}

package com.chhuang.service;


import com.chhuang.core.service.InterfaceService;
import com.chhuang.model.ChUser;
import com.chhuang.mapper.ChUserMapper;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * @ClassName ChUserService
 * @Description ch_user表服务层(ChUserService)
 * @Author Darren Huang
 * @Date 2022-11-19 01:13:03
 * @Version 1.0
 */
public interface ChUserService extends InterfaceService<ChUser> {

}
package com.chhuang.service.impl;

import com.chhuang.model.ChUser;
import com.chhuang.mapper.ChUserMapper;
import com.chhuang.service.ChUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @ClassName ChUserServiceImpl
 * @Description ch_user表服务层实现类(ChUserServiceImpl)
 * @Author Darren Huang
 * @Date 2022-11-19 18:56:32
 * @Version 1.0
 */
@Transactional
@Service("chUserService")
public class ChUserServiceImpl extends ServiceImpl<ChUserMapper, ChUser> implements ChUserService {
    @Autowired
    private ChUserMapper chUserMapper;
}
    @GetMapping("/test")
    @ApiOperation(value = "test", notes = "test")
    public boolean test(String name){
        log.info("ID存在{}",chUserService.exists(new QueryWrapper<ChUser>().eq("user_id", name)));
        return chUserService.exists(new LambdaQueryWrapper<ChUser>().eq(ChUser::getUsername, name));
    }

在controller测试一下是不是能用。还是不错的。大家互相学习一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值