1、mybatis-pus是我们在工作和学习中常用的一个orm框架,在编写的代码的过程中,就突然想将mp的相关操作再次封装一下,于是就干了,记录一下相关的过程。
2、不知道什么是mybatis-pus的,可以直接参考mysbatis-pus的官网
3、首先导包(包还没开发完),在实体类中加入注解,如:
@ApiModelProperty(value = "id",hidden = true)
@OrderBy(value = "id",sort = 3)
private Long id;
@ApiModelProperty(hidden = true)
@OrderBy(value = "is_system",sort = 2)
private Integer isSystem;
@ApiModelProperty(hidden = true)
@OrderBy(value = "is_default")
private Integer isDefault;
@ApiModelProperty(value = "名字")
@MpQuery(value = "name",condition = QueryConstant.LIKE_RIGHT)
private String name;
4、使用api获取分页数据:
MybatisPusBean<WallpaperDetailDTO, WallpaperDetail,WallpaperDetailVO> mybatisPusBean = new MybatisPusBean<>(wallpaperDetailDTO,wallpaperDetailService,wallpaperDetailDTO,WallpaperDetail.class,WallpaperDetailVO.class);
IPage<TestVO> pageR = mybatisPusBean.getPageR();
注意:wallpaperDetailDTO需要继承PageInfo
这样就完成了对数据的查询了,看简单吧。
4、开发过程中目前就使用到了两个注解:OrderBy和MpQuery
/**
* mp排序注解
* @Auther liuhaijin
* @Date 2022/1/24
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OrderBy {
// 数据据库字段名
String value() default "";
// 排序方式
String sortValue() default QueryConstant.DESC;
// 排序权重 值越大字段就越排在后面
int sort() default 1;
}
/**
* mp查询注解
* @Auther liuhaijin
* @Date 2022/1/24
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MpQuery {
// 数据库字段
String value() default "";
// 查询条件
String condition() default QueryConstant.EQ;
}
5、然后我们来看一下注解中所使用到的相关字段
(1)首先是OrderBy 注解:
// 数据据库字段名 默认值为倒序
String value() default OrderByConstant.DESC;
其中用到了一个常量类,如下:
/**
* 查询排序常量
* @Auther liuhaijin
* @Date 2022/1/25
*/
public interface OrderByConstant {
// 倒序
String DESC = "desc";
// 正序
String ASC = "asc";
}
/**
* mp查询注解
* @Auther liuhaijin
* @Date 2022/1/24
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MpQuery {
// 数据库字段
String value() default "";
// 查询条件
String condition() default QueryConstant.EQ;
}
// 查询条件
String condition() default QueryConstant.EQ;
其中用到了一个常量类,如下:
/**
* mp查询常量
* @Auther liuhaijin
* @Date 2022/1/24
*/
public interface QueryConstant {
String AND = "and"; // 和
String OR = "or"; // 或
String NESTED = "nested"; // 嵌套
String EQ = "eq"; //等于
String NE = "ne"; //不等于
String GT = "gt"; //大于
String GE = "ge"; //大于等于
String LT = "lt"; //小于
String LE = "le"; //小于等于
String BETWEEN = "between"; // 在...之间
String NOT_BETWEEN = "notBetween"; // 不在...之间
String LIKE = "like"; // 模糊查询
String NOT_LIKE = "notLike"; // 非模糊查询
String LIKE_LEFT = "likeLeft"; // 左模糊
String LIKE_RIGHT = "likeRight"; // 右模糊查询
String IN = "in"; // 选择查询
String NOT_IN = "notIn"; // 非选择查询
String IS_NULL = "isNull"; // 为空
String IS_NOT_NULL = "isNotNull"; // 不为空
String CONTAIN_ARRAY = "contain"; // 包含
String CONTAINED_BY_ARRAY = "contained_by"; // 被包含
String OVERLAP_ARRAY = "overlap"; // 重叠
String ASC = "asc"; // 正序
String DESC = "desc"; // 倒序
String DATE = "date"; // 日期
String TIMESTAMP = "timestamp"; // 时间戳
}
使用到了两个自定义的实体类,见注解,很简单的,不过多说明
/**
* @Auther liuhaijin
* @Date 2022/1/24
*/
@Data
public class ColumnBean {
// 字段属性名称
private String columnName;
// 字段属性值
private Object columnValue;
// 数据库查询值 注解value的值
private String queryValue;
// 查询条件 注解condition的值
private String queryCondition;
}
/**
* 查询排序注解实体对象
* @Auther liuhaijin
* @Date 2022/1/25
*/
@Data
public class OrderByBean {
// 数据库排序字段
private String column;
// 排序的方式
private String orderByValue;
// 排序的权重
private Integer sort;
}
然后就是最重要的一个核心的内容,其中运用到了大量的发射,在实际运用的时候可能对性能造成影响:
package xyz.haijin.mybatisplus.bean;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import xyz.haijin.mybatisplus.annotation.MpQuery;
import xyz.haijin.mybatisplus.annotation.OrderBy;
import xyz.haijin.mybatisplus.model.PageBean;
import xyz.haijin.mybatisplus.model.PageInfo;
import xyz.haijin.mybatisplus.constant.QueryConstant;
import xyz.haijin.mybatisplus.util.BeanUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author liuhaijin
* @date 2022/4/2
* D 请求实体类 T 数据库实体类 R 返回的实体类
*/
public class MybatisPusBean<D,T,R> {
private IService<T> iService;
private PageInfo pageInfo;
private D d;
private Class<T> tClass;
private Class<R> rClass;
private IPage<T> tPage;
private IPage<R> rPage;
List<OrderByBean> orderByBeans = new ArrayList<OrderByBean>();
// 属性字段
private Map<String, ColumnBean> columnMap = new HashMap<>();
public MybatisPusBean(PageInfo pageInfo, IService<T> iService, D d, Class<T> tClass, Class<R> rClass) {
this.pageInfo = pageInfo;
this.iService = iService;
this.d = d;
this.tClass = tClass;
this.rClass = rClass;
this.tPage = new Page<>(pageInfo.getCurrent(),pageInfo.getPageSize());
this.rPage = new Page<>(pageInfo.getCurrent(),pageInfo.getPageSize());
}
public MybatisPusBean( D d, Class<T> tClass, Class<R> rClass) {
this.d = d;
this.tClass = tClass;
this.rClass = rClass;
}
public MybatisPusBean(IPage<R> rPage,D d, Class<T> tClass, Class<R> rClass) {
this.d = d;
this.tClass = tClass;
this.rClass = rClass;
this.rPage = rPage;
}
/**
* 实体对象查询
* @return
*/
public LambdaQueryWrapper<T> getLambdaQueryWrapper() {
return getQueryWrapper().lambda();
}
/**
* 分页查询
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
public IPage<T> getPage() {
if (iService == null || tPage == null) {
return null;
}
return iService.page(tPage,getLambdaQueryWrapper());
}
/**
* 获取PageBean的分页数据
* @return
*/
public PageBean<T> getPageBean() {
IPage<T> page = getPage();
return new PageBean<T>(page.getCurrent(),page.getSize(),page.getPages(),page.getTotal(),page.getRecords());
}
/**
* 获取返回实体类的数据
* @return
*/
public IPage<R> getPageR() {
IPage<T> page = getPage();
List<T> tList = page.getRecords();
if (rPage == null) {
return null;
}
List<R> rList = BeanUtils.copyProperties(tList, rClass);
rPage.setRecords(rList);
rPage.setCurrent(page.getCurrent());
rPage.setSize(page.getSize());
rPage.setPages(page.getPages());
rPage.setTotal(page.getTotal());
return rPage;
}
/**
* 获取返回实体类PageBeanR的分页数据
* @return
*/
public PageBean<R> getPageBeanR() {
IPage<R> page = getPageR();
return new PageBean<>(page.getCurrent(), page.getSize(), page.getPages(), page.getTotal(), page.getRecords());
}
/**
* 实体对象查询
* @return
*/
public QueryWrapper<T> getQueryWrapper() {
T t = null;
try {
t = checkAnnotation(d);
} catch (IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
QueryWrapper<T> queryWrapper = Wrappers.query(t);
if (orderByBeans.size() != 0) {
List<String> asc = new ArrayList<String>();
List<String> desc = new ArrayList<String>();
List<OrderByBean> collect = orderByBeans.stream().sorted((Comparator.comparing(OrderByBean::getSort))).collect(Collectors.toList());
for (OrderByBean orderByBean : collect) {
if (QueryConstant.ASC.equals(orderByBean.getOrderByValue())) {
asc.add(orderByBean.getColumn());
} else if (QueryConstant.DESC.equals(orderByBean.getOrderByValue())) {
desc.add(orderByBean.getColumn());
}
}
if (asc.size() != 0) {
queryWrapper.orderByAsc(String.valueOf(asc.toArray(new String[0])));
}
if (desc.size() != 0) {
queryWrapper.orderByDesc(String.valueOf(desc.toArray(new String[0])));
}
}
return buildQueryWrapper(queryWrapper);
}
private QueryWrapper<T> buildQueryWrapper(QueryWrapper<T> queryWrapper) {
if (columnMap.size() != 0) {
for (Map.Entry<String, ColumnBean> stringColumnBeanEntry : columnMap.entrySet()) {
ColumnBean columnBean = stringColumnBeanEntry.getValue();
// TODO 构建查询条件
switch (columnBean.getQueryCondition()) {
case QueryConstant.LIKE_RIGHT: // 右模糊查询
queryWrapper.likeRight(columnBean.getQueryValue(),columnBean.getColumnValue());
break;
case QueryConstant.GE: //大于等于
queryWrapper.ge(columnBean.getQueryValue(),columnBean.getColumnValue());
break;
case QueryConstant.LE: //小于等于
queryWrapper.le(columnBean.getQueryValue(),columnBean.getColumnValue());
break;
default:
break;
}
}
}
return queryWrapper;
}
/**
* 校验注解
* @param d 传入的数据实体对象
*/
private T checkAnnotation(D d) throws IllegalAccessException, InstantiationException {
T t = tClass.newInstance();
Class<?> dClass = d.getClass();
// 向上循环 遍历父类
for (; dClass != Object.class; dClass = dClass.getSuperclass()) {
for (Field field : dClass.getDeclaredFields()) {
if (field.getAnnotation(MpQuery.class) != null) {
String value = field.getAnnotation(MpQuery.class).value();
if ("".equals(value)) {
setFieldValue(field,t);
continue;
}
field.setAccessible(true);
Object object = field.get(d);
if (object != null) {
String condition = field.getAnnotation(MpQuery.class).condition();
ColumnBean columnBean = new ColumnBean();
String name = field.getName();
columnBean.setColumnName(name);
columnBean.setColumnValue(object);
columnBean.setQueryCondition(condition);
columnBean.setQueryValue(value);
columnMap.put(name,columnBean);
}
} else {
setFieldValue(field,t);
}
if (field.getAnnotation(OrderBy.class) != null) {
String sortValue = field.getAnnotation(OrderBy.class).sortValue();
String column = field.getAnnotation(OrderBy.class).value();
int sort = field.getAnnotation(OrderBy.class).sort();
OrderByBean orderByBean = new OrderByBean();
orderByBean.setColumn(column);
orderByBean.setOrderByValue(sortValue);
orderByBean.setSort(sort);
orderByBeans.add(orderByBean);
}
}
}
return t;
}
/**
* 通过反射设置字段值
* @param field
* @return
*/
private void setFieldValue(Field field,T t) throws IllegalAccessException {
for (Field tClassField : tClass.getDeclaredFields()) {
// 判断反射的Field是不是用final修饰
if (Modifier.isFinal(field.getModifiers())) {
return;
}
if (tClassField.getName().equals(field.getName())) {
field.setAccessible(true);
Object object = field.get(d);
tClassField.setAccessible(true);
tClassField.set(t,object);
}
}
}
}
就目前来说,只实现了对右模糊、大于等于和小于等于的操作,其他的再说吧!
注意:mybatis-plus 在3.4.0版本以上分页插件不一样了,详情请参考官网