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(); }
关联数据查询接口(单实例查询)

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(); }
关联对象(单个详情对象)数据查询工具

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; } }
静态获取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(); } }
使用
关联调用的数据服务类
@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(); } }