mybatis-pus学习之再次封装

我爱海鲸 2022-04-07 18:06:50 暂无标签

简介将mp的相关api再次封装,使用注解进行查询操作的封装

1、mybatis-pus是我们在工作和学习中常用的一个orm框架,在编写的代码的过程中,就突然想将mp的相关操作再次封装一下,于是就干了,记录一下相关的过程。

小姐姐

2、不知道什么是mybatis-pus的,可以直接参考mysbatis-pus的官网

mybatis-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版本以上分页插件不一样了,详情请参考官网












你好:我的2025