Mybatis-plus通用查询方法封装

定义DTO

package com.lbdj.user.service.dto;

import com.lbdj.toolkit.utils.ReturnField;
import com.lbdj.toolkit.utils.SFunction;
import lombok.Data;

/**
 * 用户DTO
 *
 * @author 作者
 * @since 2023-06-27
 */
@Data
public class LbdjUserDTO {

    /**
     * 主键
     */
    private Long id;


    private String userNo;

    /**
     * 昵称
     */
    private String nickName;

    /**
     * 密码
     */
    private String password;

    /**
     * 查询条数
     */
    private Integer limit;

    /**
     * 需要返回的列(DTO列名)
     */
    private String columnStr;

    public <T> void setReturnField(SFunction<T, ?>... columns) {
        this.columnStr = ReturnField.select(columns);
    }
}

DTO调用方式

 工具类1(适用在没有mybatis-plus包的情况下)

package com.lbdj.toolkit.utils;

import java.io.Serializable;
import java.util.function.Function;

@FunctionalInterface
public interface SFunction<T, R> extends Function<T, R>, Serializable {
}
package com.lbdj.toolkit.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;

@SuppressWarnings("unused")
public class SerializedLambda implements Serializable {

    private static final long serialVersionUID = 8025925345765570181L;

    private Class<?> capturingClass;
    private String functionalInterfaceClass;
    private String functionalInterfaceMethodName;
    private String functionalInterfaceMethodSignature;
    private String implClass;
    private String implMethodName;
    private String implMethodSignature;
    private int implMethodKind;
    private String instantiatedMethodType;
    private Object[] capturedArgs;

    /**
     * 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象
     *
     * @param lambda lambda对象
     * @return 返回解析后的 SerializedLambda
     */
    public static SerializedLambda resolve(SFunction<?, ?> lambda) {
        if (!lambda.getClass().isSynthetic()) {
            throw new RuntimeException("该方法仅能传入 lambda 表达式产生的合成类");
        }
        try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(serialize(lambda))) {
            @Override
            protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                Class<?> clazz;
                try {
                    clazz = toClassConfident(objectStreamClass.getName());
                } catch (Exception ex) {
                    clazz = super.resolveClass(objectStreamClass);
                }
                return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
            }
        }) {
            return (SerializedLambda) objIn.readObject();
        } catch (ClassNotFoundException | IOException e) {
            throw new RuntimeException("This is impossible to happen",e);
        }
    }

    /**
     * 获取接口 class
     *
     * @return 返回 class 名称
     */
    public String getFunctionalInterfaceClassName() {
        return normalizedName(functionalInterfaceClass);
    }


    /**
     * 获取 class 的名称
     *
     * @return 类名
     */
    public String getImplClassName() {
        return normalizedName(implClass);
    }

    /**
     * 获取实现者的方法名称
     *
     * @return 方法名称
     */
    public String getImplMethodName() {
        return implMethodName;
    }

    /**
     * 正常化类名称,将类名称中的 / 替换为 .
     *
     * @param name 名称
     * @return 正常的类名
     */
    private String normalizedName(String name) {
        return name.replace('/', '.');
    }

    /**
     * @return 获取实例化方法的类型
     */
    public Class<?> getInstantiatedType() {
        String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')));
        return toClassConfident(instantiatedTypeName);
    }

    /**
     * @return 字符串形式
     */
    @Override
    public String toString() {
        String interfaceName = getFunctionalInterfaceClassName();
        String implName = getImplClassName();
        return String.format("%s -> %s::%s",
                interfaceName.substring(interfaceName.lastIndexOf('.') + 1),
                implName.substring(implName.lastIndexOf('.') + 1),
                implMethodName);
    }


    public static Class<?> toClassConfident(String name) {
        try {
            return classForName(name);
        } catch (ClassNotFoundException e) {
            try {
                return Class.forName(name);
            } catch (ClassNotFoundException ex) {
                throw new RuntimeException("找不到指定的class!请仅在明确确定会有 class 的时候,调用该方法", e);
            }
        }
    }

    private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();

    public static Class<?> classForName(String className) throws ClassNotFoundException {
        return classLoaderWrapper.classForName(className);
    }

    public static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(object);
            oos.flush();
        } catch (IOException ex) {
            throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
        }
        return baos.toByteArray();
    }
}
package com.lbdj.toolkit.utils;

public class ClassLoaderWrapper {

  ClassLoader defaultClassLoader;
  ClassLoader systemClassLoader;

  ClassLoaderWrapper() {
    try {
      systemClassLoader = ClassLoader.getSystemClassLoader();
    } catch (SecurityException ignored) {
      // AccessControlException on Google App Engine
    }
  }

  public Class<?> classForName(String name) throws ClassNotFoundException {
    return classForName(name, getClassLoaders(null));
  }

  Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
    for (ClassLoader cl : classLoader) {
      if (null != cl) {
        try {
          return Class.forName(name, true, cl);
        } catch (ClassNotFoundException e) {
          // we'll ignore this until all classloaders fail to locate the class
        }
      }
    }
    throw new ClassNotFoundException("Cannot find class: " + name);
  }

  ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
        classLoader,
        defaultClassLoader,
        Thread.currentThread().getContextClassLoader(),
        getClass().getClassLoader(),
        systemClassLoader};
  }

}
package com.lbdj.toolkit.utils;

import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通过lambda获取字段名
 */
public class ReturnField {

    /**
     * SerializedLambda 反序列化缓存
     */
    private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();

    @SafeVarargs
    public final static <T> String select(SFunction<T, ?>... columns) {
        if(columns == null || columns.length == 0){
            return null;
        }
        HashSet<String> returnField = new HashSet<>(8);
        Arrays.stream(columns).forEach(col -> {
            String fieldName = parseFunction(col);
            returnField.add(fieldName);
        });
        StringBuffer colStrBuffer = new StringBuffer();
        returnField.forEach(m -> {
            colStrBuffer.append(m).append(",");
        });
        if (colStrBuffer.toString().endsWith(",")) {
            colStrBuffer.replace(colStrBuffer.toString().length() - 1, colStrBuffer.toString().length(), "");
        }
        String colStr = colStrBuffer.toString();
        return colStr;
    }

    public static <T> String parseFunction(SFunction<T, ?> function) {
        SerializedLambda serializedLambda = resolve(function);
        String fieldName = methodToProperty(serializedLambda.getImplMethodName());
        return fieldName;
    }

    public static String methodToProperty(String name) {
        if (name.startsWith("is")) {
            name = name.substring(2);
        } else {
            if (!name.startsWith("get") && !name.startsWith("set")) {
                throw new RuntimeException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
            }
            name = name.substring(3);
        }
        if (name.length() == 1 || name.length() > 1 && !Character.isUpperCase(name.charAt(1))) {
            name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
        }
        return name;
    }

    public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
        Class<?> clazz = func.getClass();
        String name = clazz.getName();
        return Optional.ofNullable(FUNC_CACHE.get(name))
                .map(WeakReference::get)
                .orElseGet(() -> {
                    SerializedLambda lambda = SerializedLambda.resolve(func);
                    FUNC_CACHE.put(name, new WeakReference<>(lambda));
                    return lambda;
                });
    }
}

工具类2(适用在有mybatis-plus包的情况下)

Mapper通用查询方法

    @Override
    public List<LbdjUserDTO> selectBase(LbdjUserDTO request) {
        LbdjUser user = BeanConvertUtils.convert(request, LbdjUser::new, null);
        QueryWrapper<LbdjUser> queryWrapper = new QueryWrapper<>();
        //封装返回字段&查询条件
        InitCommonQueryUtils.initQuery(user, request.getColumnStr(), queryWrapper);
        queryWrapper.last(" limit " + request.getLimit());
        List<LbdjUser> result = list(queryWrapper);
        if (CollectionUtils.isEmpty(result)) {
            return Arrays.asList();
        }
        return BeanConvertUtils.convertList(result, LbdjUserDTO::new);
    }
package com.lbdj.user.service.common.utils;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lbdj.user.service.common.advice.exception.RRException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class InitCommonQueryUtils {
    public static <T> void initQuery(T entity, String columnStr, QueryWrapper<T> queryWrapper) {
        Class<T> type = (Class<T>) entity.getClass();
        TableName annotation = type.getAnnotation(TableName.class);
        if (annotation == null) {
            throw new RRException("非数据库实体类");
        }
        //返回字段
        StringBuilder columns = new StringBuilder();
        //查询条件
        HashMap<String, Object> paramMap = new HashMap<>();

        Field[] declaredFields = type.getDeclaredFields();
        List<String> columnArr = null;
        if (null != columnStr && !"".equals(columnStr)) {
            columnArr = Arrays.asList(columnStr.split(","));
        }
        /**
         * 有兼容历史问题,表中字段半驼峰、非驼峰问题
         */
        for (Field declaredField : declaredFields) {
            //设置属性可访问
            declaredField.setAccessible(true);
            //属性名
            String name = declaredField.getName();
            //获取主键
            TableId tableId = declaredField.getAnnotation(TableId.class);
            //获取非主键的
            TableField tableField = declaredField.getAnnotation(TableField.class);
            //拼接返回字段
            appendReturnField(name, columnArr, columns, tableId, tableField);
            //拼接查询条件
            appendCondition(entity, paramMap, declaredField, name, tableId, tableField);
        }

        //返回字段
        if (columns.length() > 0) {
            queryWrapper.select(columns.toString());
        }
        //查询条件
        if (paramMap.size() > 0) {
            queryWrapper.allEq(paramMap, false);
        }
    }

    private static void appendReturnField(String name,
                                          List<String> columnArr,
                                          StringBuilder columns,
                                          TableId tableId,
                                          TableField tableField) {
        if (null == columnArr) {
            return;
        }
        if (!columnArr.contains(name)) {
            return;
        }
        if (tableId != null) {
            if (columns.length() > 0) {
                columns.append(",");
            }
            columns.append(tableId.value());
            return;
        }
        if (tableField != null) {
            if (columns.length() > 0) {
                columns.append(",");
            }
            if (tableField.exist()) {
                //是数据表字段,不是数据表字段不处理
                columns.append(tableField.value());
            }
        }
    }

    private static <T> void appendCondition(T entity,
                                            HashMap<String, Object> paramMap,
                                            Field declaredField,
                                            String name,
                                            TableId tableId,
                                            TableField tableField) {
        // 获取属性的值
        Object value = null;
        try {
            value = declaredField.get(entity);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        if (null == value) {
            return;
        }
        if (tableId != null) {
            paramMap.put(tableId.value(), value);
            return;
        }
        if (tableField != null) {
            if (tableField.exist()) {
                //是数据表字段,不是数据表字段不处理
                paramMap.put(tableField.value(), value);
            }
            return;
        }
        //处理没有加注解的属性(兼容完全服务驼峰规范的数据表)
        if (!Modifier.isStatic(declaredField.getModifiers())) {
            paramMap.put(name, value);
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Mybatis-Plus一个基于Mybatis的增强工具,提供了许多实用的功能,如自动生成代码、分页查询、条件构造器、性能分析等。Mybatis-Plus Service是Mybatis-Plus一个模块,提供了一些常用的Service层接口和实现类,如IService、ServiceImpl等,方便开发者快速构建Service层。 ### 回答2: Mybatis-Plus一个开源的、能够和Mybatis无缝衔接并扩展出更多实用功能的框架。在实际项目开发中,通常会使用到基于Mybatis-Plus的Service层,以下是关于Mybatis-Plus Service的一些介绍。 Mybatis-Plus的Service层是基于Mybatis-Plus框架进行封装的,旨在简化开发者编写Service层代码的流程。使用Mybatis-Plus Service可以有效地减少重复代码的编写,提高开发效率。 在Mybatis-Plus Service中,通常包含了一些常见的CRUD方法,如查询列表、根据ID查询、插入、更新和删除等。我们可以通过继承BaseService或者IService来使用这些方法。同时,Mybatis-Plus Service还提供了一些强大的查询构建器,如LambdaQueryWrapper和QueryWrapper等,可以快速构建复杂的查询条件。 另外,Mybatis-Plus Service还支持事务管理。它提供了一种@Transactional注解来实现声明式事务,我们只需在Service层的方法上添加该注解,即可完成事务的配置。 除了基本的CRUD操作和事务管理外,Mybatis-Plus Service还具有其他扩展的功能,例如分页查询、批量操作、逻辑删除等。这些功能都能够极大地简化开发者的编码工作。 总而言之,Mybatis-Plus Service是一种基于Mybatis-Plus框架的封装,用于简化Service层代码的编写。它提供了一系列的CRUD方法、事务管理以及其他实用功能,可以提高开发效率并减少冗余代码的编写。使用Mybatis-Plus Service,开发者能够更加专注于业务逻辑的实现,提高开发效率和代码质量。 ### 回答3: MyBatis-Plus一个MyBatis基础上的增强工具,提供了更加便捷的CRUD操作方式。其中的Service是MyBatis-Plus提供的一层封装,主要用于处理业务逻辑和数据库操作之间的关系。 MyBatis-Plus的Service主要有以下几个功能: 1. 提供通用的CRUD方法:Service提供了常见的增删改查方法,如save、remove、update等,可以直接调用这些方法来操作数据库,无需手写SQL语句。 2. 封装条件构造器:Service的方法中可以使用MyBatis-Plus提供的条件构造器来进行查询条件的组装,例如可以使用eq、like、in等方法来构建查询条件。 3. 支持分页查询:Service提供了分页查询的方法,可以方便地进行数据分页查询操作。可以设置每页的数量、当前页码等参数来实现分页效果。 4. 支持事务控制:Service可以通过注解的方式来对方法添加事务控制,保证在业务逻辑中的多个操作要么全部成功,要么全部失败。可以使用@Transactional注解来标记需要进行事务控制的方法。 总的来说,MyBatis-Plus的Service提供了一种更加便捷的数据库操作方式,简化了开发过程中的数据库操作代码,提高了开发效率。同时,它还具备一些高级功能,如条件构造器、分页查询和事务控制,使得开发者可以更加灵活和方便地进行业务逻辑的处理和数据库操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值