JAVA 连表查询工具类

关联数据查询接口(队列实例查询)

import java.lang.annotation.*;

/**
 * 关联数据查询接口(队列实例查询)
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RelationListData {
    /**
     * 注入在spring容器中的bean类
     */
    Class clazz();

    /**
     * 执行bean的方法,方法的参数定义名要跟relationField保持一致
     */
    String methodName();

    /**
     * 用于外键查询的字段
     * 多字段对应methodName的多参数
     */
    String[] relationField();

    /**
     * 当前关键key,根据keyField作为key从结果中获取数据,一般是id
     * @return
     */
    String keyField();

    /**
     * 结果关键key,返回的数据根据keyField进行分组,一般是关联外键id
     * @return
     */
    String resultKeyField();
}
View Code
关联数据查询接口(单实例查询)
import java.lang.annotation.*;
import java.util.List;

/**
 * 关联数据查询接口(单实例查询)
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RelationSingData {
    /**
     * 注入在spring容器中的bean类
     */
    Class clazz();

    /**
     * 执行bean的方法,方法的参数定义名要跟relationField保持一致
     */
    String methodName();

    /**
     * 用于外键查询的字段
     * 多字段对应methodName的多参数
     */
    String[] relationField();

    /**
     * 关联对象是否为列表
     */
    boolean list();
}
View Code
关联对象(单个详情对象)数据查询工具
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 关联对象(单个详情对象)数据查询工具
 * @Author : cxw
 * @Date : 2023/8/23 17:46
 * @Version : 1.0
 **/
public class RelationUtils {

    /**
     * 单对象获取字段关联数据
     * @param obj
     * @throws Exception
     */
    public static <T> void getListRealtion(List<T> objs) throws Exception {
        if(CollectionUtils.isEmpty(objs))return;
        Object obj = objs.get(0);
        List<Field> fields =  listFields(obj.getClass());
        Map<String, Field> fieldsMap = fields.stream().collect(Collectors.toMap(Field::getName, it -> it));
        //先获取要处理的字段
        List<Field> queryField=getQueryField(fields,RelationListData.class);
        for (Field field : queryField) {
            if(!hasAnnotation(field, RelationListData.class)) continue;
            RelationListData relationData=field.getAnnotation(RelationListData.class);
            // 获取字段值
            Field retField = field;
            retField.setAccessible(true);
            // 注解信息
            Class clazz = relationData.clazz();
            String[] relationField = relationData.relationField();
            String methodName = relationData.methodName();
            String keyField = relationData.keyField();
            String resultKeyField = relationData.resultKeyField();
            // 获取参数
            Map<String,Object> param=getListParam(fieldsMap,relationField,objs);
            // 获取类,并且执行操作
            List<Object> resultList = (List<Object>) SpringBeanStaticUtil.invokeService(clazz, methodName, param);
            if(CollectionUtils.isEmpty(resultList))return;
            Map<Object,List<Object>> resultMap = resultToResultMap(resultKeyField,resultList);
            //赋值
            for (Object object : objs) {
                Field _keyField = fieldsMap.get(keyField);
                Object keyVal = _keyField.get(object);
                List<Object> objects = resultMap.get(keyVal);
                field.set(object,objects);
            }
        }
    }

    /**
     * 返回列表数据变map
     * @param resultKeyField
     * @param resultList
     * @return
     */
    private static Map<Object, List<Object>> resultToResultMap(String resultKeyField, List<Object> resultList) throws IllegalAccessException {
        Map<Object, List<Object>> result=new HashMap<>();
        Object obj = resultList.get(0);
        List<Field> fields =  listFields(obj.getClass());
        //获取resultKeyField字段
        Field field=null;
        for (Field item : fields) {
            if(item!=null&&resultKeyField.equals(item.getName())){
                field=item;
                field.setAccessible(true);
                break;
            }
        }
        //组装成map
        for (Object item : resultList) {
            Object key = field.get(item);
            List<Object> objects = result.get(key);
            if(CollectionUtils.isEmpty(objects))objects=new ArrayList<>();
            objects.add(item);
            result.put(key,objects);
        }
        return result;
    }

    /**
     * 单对象获取字段关联数据
     * @param obj
     * @throws Exception
     */
    public static void getSingRealtion(Object obj) throws Exception {
        List<Field> fields =  listFields(obj.getClass());
        Map<String, Field> fieldsMap = fields.stream().collect(Collectors.toMap(Field::getName, it -> it));
        for (Field field : fields) {
            if(!hasAnnotation(field, RelationSingData.class)) continue;
            RelationSingData relationData=field.getAnnotation(RelationSingData.class);
            // 获取字段值
            Field retField = field;
            retField.setAccessible(true);
            // 注解信息
            Class clazz = relationData.clazz();
            String[] relationField = relationData.relationField();
            String methodName = relationData.methodName();
            boolean isList = relationData.list();
            // 获取参数
            Map<String,Object> param=getParam(fieldsMap,relationField,obj);
            // 获取类,并且执行操作
            Object result = SpringBeanStaticUtil.invokeService(clazz, methodName, param);
            if(isList){
                List<Object> resultList = (List<Object>) result;
                field.set(obj,resultList);
            }else {
                field.set(obj,result);
            }
        }
    }

    /**
     * 根据注解获取参数值
     * @param fieldsMap
     * @param relationField
     * @param obj
     * @return
     */
    private static Map<String, Object> getParam(Map<String, Field> fieldsMap, String[] relationField, Object obj) throws IllegalAccessException {
        Map<String, Object> result = new HashMap<>();
        for (String fieldName : relationField) {
            Field field = fieldsMap.get(fieldName);
            if(field==null){
                result.put(fieldName,null);
                continue;
            }
            field.setAccessible(true);
            result.put(fieldName,field.get(obj));
        }
        return result;
    }

    /**
     * 获取参数列表
     * @param fieldsMap
     * @param relationField
     * @param objs
     * @return
     */
    private static <T> Map<String, Object> getListParam(Map<String, Field> fieldsMap, String[] relationField, List<T> objs) throws IllegalAccessException {
        Map<String, Object> result = new HashMap<>();
        for (String fieldName : relationField) {
            Field field = fieldsMap.get(fieldName);
            if(field==null){
                result.put(fieldName,new ArrayList<>());
                continue;
            }
            field.setAccessible(true);
            List<Object> list=new ArrayList<>();
            for (Object obj : objs) {
                list.add(field.get(obj));
            }
            result.put(fieldName,list);
        }
        return result;
    }

    /**
     * 通过对象.class获取所有Fields,包括父类
     * @param cls
     * @return
     */
    private static List<Field> listFields(Class<?> cls){
        Field[] fs = cls.getDeclaredFields();
        List<Field> fields = new ArrayList<>(Arrays.asList(fs));
        if (cls.getSuperclass() !=null){
            fields.addAll(listFields(cls.getSuperclass()));
        }
        return fields;
    }

    /**
     * 是否存在注解
     * @param field
     * @param annotation
     * @return
     */
    private static boolean hasAnnotation(Field field, Class annotation){
        Annotation aim = field.getAnnotation(annotation);
        if(aim!=null){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 获取需要处理的字段值
     * @param fields
     * @return
     */
    private static List<Field> getQueryField(List<Field> fields,Class clazz) {
        List<Field> result=new ArrayList<>();
        for (Field field : fields) {
            if (!hasAnnotation(field, clazz)) continue;
            result.add(field);
        }
        return result;
    }

}
View Code
静态获取bean对象
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.DefaultParameterNameDiscoverer;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Description : 静态获取bean对象
 * @Author : cxw
 * @Date : 2023/8/24 20:10
 * @Version : 1.0
 **/
@Configuration
public class SpringBeanStaticUtil implements ApplicationContextAware {

    @Autowired
    private static ApplicationContext applicationContext;

    private static final List<Class> WRAP_CLASS = Arrays.asList(Integer.class, Boolean.class, Double.class,Byte.class,
            Short.class, Long.class, Float.class, Double.class, BigDecimal.class, String.class,List.class);

    public void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    /**
     * 反射调用spring bean方法的入口
     * @param classz 类名
     * @param methodName 方法名
     * @param paramMap 实际参数
     * @throws Exception
     */
    public static Object invokeService(Class classz, String methodName, Map<String,Object> paramMap) throws Exception {
        // 从Spring中获取代理对象(可能被JDK或者CGLIB代理)
        Object proxyObject = applicationContext.getBean(classz);

        // 获取代理对象执行的方法
        Method method = getMethod(proxyObject.getClass(), methodName);

        // 获取代理对象中的目标对象
        Class target = AopUtils.getTargetClass(proxyObject);

        // 获取目标对象的方法,为什么获取目标对象的方法:只有目标对象才能通过 DefaultParameterNameDiscoverer 获取参数的方法名,代理对象由于可能被JDK或CGLIB代理导致获取不到参数名
        Method targetMethod = getMethod(target, methodName);

        if(method == null || targetMethod == null) {
            throw new RuntimeException(String.format("没有找到%s方法", methodName));
        }

        // 获取方法执行的参数
        List<Object> objects = getMethodParamList(targetMethod, paramMap);

        // 执行方法
        return method.invoke(proxyObject, objects.toArray());
    }

    /**
     * 获取目标方法
     * @param proxyObject
     * @param methodStr
     * @return
     */
    private static Method getMethod(Class proxyObject, String methodStr) {
        Method[] methods = proxyObject.getMethods();
        for(Method method : methods) {
            if(method.getName().equalsIgnoreCase(methodStr)) {
                return method;
            }
        }
        return null;
    }

    /**
     * 获取方法实际参数,不支持基本类型
     * @param method
     * @param paramMap
     * @return
     */
    private static List<Object> getMethodParamList(Method method, Map<String, Object> paramMap) throws Exception {
        List<Object> objectList = new ArrayList<>();

        // 利用Spring提供的类获取方法形参名
        DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
        String[] param =  nameDiscoverer.getParameterNames(method);

        for (int i = 0; i < method.getParameterTypes().length; i++) {
            Class<?> parameterType = method.getParameterTypes()[i];

            Object object = null;
            // 基本类型不支持,支持包装类
            if(WRAP_CLASS.contains(parameterType)) {
                if(param != null && paramMap.containsKey(param[i])){
                    object = paramMap.get(param[i]);

                    object = ConvertUtils.convert(object, parameterType);
                }

            }else if (!parameterType.isPrimitive() ) {
                object = getInstance(parameterType);

                // 赋值
                BeanUtils.populate(object, paramMap);
            }

            objectList.add(object);
        }

        return objectList;
    }

    /**
     * 获取类型实例
     * @param parameterType
     * @return
     * @throws Exception
     */
    private static Object getInstance(Class<?> parameterType) throws Exception {
        if(parameterType.isAssignableFrom(List.class)) {
            return  new ArrayList();

        }else if(parameterType.isAssignableFrom(Map.class)) {
            return new HashMap();
        }else if(parameterType.isAssignableFrom(Set.class)) {
            return  new HashSet();
        }
        return parameterType.newInstance();
    }
}
View Code

 

使用

关联调用的数据服务类

    @RelationListData(clazz = RoleMenuService.class,methodName = "getByRoleIds",relationField = "id",keyField = "id",resultKeyField = "roleId")
    private List<RoleMenuVO> menuVOS;
    @RequestMapping("/getAll")
    public List<RoleListVo> getAll() throws Exception {

        List<Role> role =roleService.getAll();
        if(CollectionUtils.isEmpty(role))return new ArrayList<>();
        List<RoleListVo> result=new ArrayList<>();
        for (Role role1 : role) {
            RoleListVo item=new RoleListVo();
            BeanUtils.copyProperties(role1,item);
            result.add(item);
        }
        RelationUtils.getListRealtion(result);
        return result;
    }

    @RequestMapping("/get")
    public RoleVo get(String id) throws Exception {
        RoleVo data=new RoleVo();
        Role role =roleService.getById(id);
        if(role==null)return data;
        BeanUtils.copyProperties(role,data);
        List<RoleMenu> menus =  roleMenuService.getByRoleId(id);
        if(CollectionUtils.isEmpty(menus))return data;
//        List<RoleMenuVO> menusVo = new ArrayList<>();
//        for (RoleMenu menu : menus) {
//            RoleMenuVO item=new RoleMenuVO();
//            BeanUtils.copyProperties(menu,item);
//            menusVo.add(item);
//        }
//        data.setMenuVOS(menusVo);
        RelationUtils.getSingRealtion(data);
        return data;
    }
/**
 * @Description : TODO
 * @Author : cxw
 * @Date : 2023/8/23 13:49
 * @Version : 1.0
 **/
@Service
public class RoleMenuService {

    @Autowired
    private RoleMenuMapper mapper;

    public List<RoleMenu> getByRoleId(String id) {
        return mapper.getByRoleId(id);
    }

    public List<RoleMenu> getByRoleIds(List<String> id) {
        if(CollectionUtils.isEmpty(id))return new ArrayList<>();
        return mapper.getByRoleIds(id);
    }
}
/**
 * @Description : TODO
 * @Author : cxw
 * @Date : 2023/8/23 13:49
 * @Version : 1.0
 **/
@Service
public class RoleService {

    @Autowired
    private RoleMapper roleMapper;

    public Role getById(String id) {
        return roleMapper.getById(id);
    }

    public List<Role> getAll() {
        return roleMapper.getAll();
    }
}

 

posted @ 2023-08-25 09:35  扰扰  阅读(25)  评论(0编辑  收藏  举报