今天刷视频的时候看到说判断是否存在使用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测试一下是不是能用。还是不错的。大家互相学习一下。