在使用MyBatis-Plus的时候,之前不知道有LambdaQueryWrapper这东西,使用的是QueryWrapper,这样就导致了一个问题,在代码里写入了数据库的列名,这样属于硬编码的方式,而且entity里已经定义了列名和属性名的对应关系,于是感到很不舒服,不可能这么好用的Mybatis Plus,还存在这么明显的不人性化的东西。经过一番百度、查看官方文档之后,得知了LambdaQueryWrapper的存在,解决了硬编码的问题。
举例:
SpuInfoEntity.java 商品spu信息
@Data
@TableName("pms_spu_info")
public class SpuInfoEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
@TableId
private Long id;
/**
* 商品名称
*/
private String spuName;
/**
* 商品描述
*/
private String spuDescription;
/**
* 所属分类id
*/
private Long catalogId;
/**
* 品牌id
*/
private Long brandId;
/**
*
*/
private BigDecimal weight;
/**
* 上架状态[0 - 下架,1 - 上架]
*/
private Integer publishStatus;
/**
*
*/
private Date createTime;
/**
*
*/
private Date updateTime;
}
使用QueryWrapper的方式:里面存在数据库列名,如spu_name
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
queryWrapper.and(wrapper ->
wrapper.eq("id", key)
.or().like("spu_name", key)
.or().like("spu_description", key)
);
if (EmptyUtil.isNotEmpty(params.get("catelogId"))) {
queryWrapper.eq("catalog_id", params.get("catelogId"));
}
IPage<SpuInfoEntity> page = this.page(
new Query<SpuInfoEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
使用LambdaQueryWrapper的方式:
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if (EmptyUtil.isNotEmpty(key)) {
queryWrapper.and(wrapper ->
wrapper.eq(SpuInfoEntity::getId, key)
.or().like(SpuInfoEntity::getSpuName, key)
.or().like(SpuInfoEntity::getSpuDescription, key)
);
}
if (EmptyUtil.isNotEmpty(params.get("catelogId"))) {
queryWrapper.eq(SpuInfoEntity::getCatalogId, params.get("catelogId"));
}
IPage<SpuInfoEntity> page = this.page(
new Query<SpuInfoEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
由上可得,LambdaQueryWrapper解耦了数据库列名与实体属性名,解决了硬编码的问题。
查看LambdaQueryWrapper的源码,发现里面用到一个Lambda解析工具类LambdaUtils,里面有个反序列化保存用的很有意思,是线程安全的ConcurrentHashMap和弱引用WeakReference的结合:
LambdaUtils.java部分源码:
/**
* SerializedLambda 反序列化缓存
*/
private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();
/**
* 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。
* 该缓存可能会在任意不定的时间被清除
*
* @param func 需要解析的 lambda 对象
* @param <T> 类型,被调用的 Function 对象的目标类型
* @return 返回解析后的结果
* @see SerializedLambda#resolve(SFunction)
*/
public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
Class<?> clazz = func.getClass();
String canonicalName = clazz.getCanonicalName();
return Optional.ofNullable(FUNC_CACHE.get(canonicalName))
.map(WeakReference::get)
.orElseGet(() -> {
SerializedLambda lambda = SerializedLambda.resolve(func);
FUNC_CACHE.put(canonicalName, new WeakReference<>(lambda));
return lambda;
});
}
附:MyBatis-Plus官方文档:简介 | MyBatis-Plus (baomidou.com)