java SDK对接金蝶
-
如果是Maven管理,可以在pom.xml中加入如下依赖:
<!-- 金蝶云对接 --> <dependency> <groupId>com.kingdee</groupId> <artifactId>k3cloud-webapi</artifactId> <version>1.0.0</version> <scope>system</scope> <!-- jar包存放的位置 --> <systemPath>${project.basedir}/lib/k3cloud-webapi-sdk7.9.2.jar</systemPath> </dependency>
-
起步配置有官方教程:查看官方指南
-
官网只提供了一些查询数据方法。对于java代码来说写起来很不舒服。下面我做了一些工具类。
一共设计了10个java文件,下面简单的介绍一下
(1) AbstractBuilder:抽象构造器,用于构建查询语句的SQL方法定义
(2) FilterRuleBuilder: 通用的查询条件构造器,继承了AbstractBuilder,可构建常用的查询字段,条件等。使用方式类比mybatis-plus的QueryWrapper
(3) Builder:针对于实体类的条件构造,继承了AbstractBuilder,修饰了FilterRuleBuilder。功能同上,使用方式类比mybatis-plus的Wrappers。注:如果不设置查询字段则查询类中所有字段
(4) ConvertType:一个类型转换的枚举类,枚举了需要转换的位置。目的是为了将金蝶中查询字段和实体类的字段之间的_与.符号的转换处理。
(5) SymbolConvert:符号转换注解,将需要指定特殊转换的字段写入该注解,即可,例:在金蝶中查询字段为A_B.C,java实体类中字段只能为A_B_C,故在该字段上标明@SymbolConvert(ConvertType.Last),表示转换字符只转最后一个。不写注解默认为转换所有符号。
(6) FormId:FormId 注解,看过API的都知道,这是标识查询金蝶的FormId值,不填默认为类名。
(7) K3Const:K3使用的静态常量
(8) SFunction:序列化函数式接口
(9)SFunctionParse:函数式接口解析,很重要,其中解析了@SymbolConvert,解析了表达式
(10) K3Api:金蝶数据接口工具类,最终使用的是这个查询,该类已注入Spring,可以通过@Autowired自动注入,作用域为一个Session。
注:FilterRuleBuilder 和 Builder类提供特有的switchAND和switchOR来切换条件判断连接符,默认是and;可通过andLeft 和 orLeft 添加 ’ AND ( ’ 与 ’ OR ( ',通过right添加 ‘)’ 。以上类代码如下:import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @Author * @Date 2022/5/16 10:03 * @Description 抽象构造器 */ public abstract class AbstractBuilder<T> { /** * 定义所有的基本类型及包装类型,或者是String */ protected static final List<String> generalType = new ArrayList<String>() {{ add(Date.class.getName()); add(Integer.class.getName()); add(Double.class.getName()); add(Float.class.getName()); add(Long.class.getName()); add(Short.class.getName()); add(Byte.class.getName()); add(Boolean.class.getName()); add(Character.class.getName()); add(String.class.getName()); add("int"); add("double"); add("float"); add("long"); add("short"); add("byte"); add("boolean"); add("char"); }}; /** * 查询参数构造器 */ protected List<String> fieldKeys = new ArrayList<>(); /** * 过滤条件构造器 */ protected StringBuilder filterStrBuilder = new StringBuilder(); /** * 排序规则条件构造器 */ protected StringBuilder orderBuilder = new StringBuilder(); /** * 返回总行数 */ protected int TopRowCount = 0; /** * 开始行索引 */ protected int StartRow = 0; /** * 最大行数 */ protected int Limit = 0; protected final String LOGIC_AND = " AND "; protected final String LOGIC_OR = " OR "; /** * 获取查询字段 * * @return */ public abstract List<String> getFieldKeys(); /** * 构建查询字段 * * @return */ public abstract String buildFieldKeys(); /** * 构造查询条件 * * @return */ public abstract String buildFilter(); /** * 构造排序条件 * * @return */ public abstract String buildOrder(); /** * 构建总行数 * * @return */ public abstract int buildTopRowCount(); /** * 构建起始行数 * * @return */ public abstract int buildStartRow(); /** * 构建最大行数 * * @return */ public abstract int buildLimit(); }
import java.lang.reflect.Field; import java.util.Date; import java.util.List; /** * @Author * @Date 2022/5/12 9:54 * @Description K3Cloud 查询条件构造 */ public class FilterRuleBuilder extends AbstractBuilder { public FilterRuleBuilder() { } /** * 逻辑关系,默认and */ protected String logic = LOGIC_AND; /** * 获取查询字段 * * @return */ public List<String> getFieldKeys() { return this.fieldKeys; } /** * 切换and逻辑 * * @return */ public FilterRuleBuilder switchAND() { logic = LOGIC_AND; return this; } /** * 切换or逻辑 * * @return */ public FilterRuleBuilder switchOR() { logic = LOGIC_OR; return this; } /** * 添加and左括号 * * @return */ public FilterRuleBuilder andLeft() { if (filterStrBuilder.length() == 0) { filterStrBuilder.append("("); } else { filterStrBuilder.append(LOGIC_AND + "("); } return this; } /** * 添加or左括号 * * @return */ public FilterRuleBuilder orLeft() { if (filterStrBuilder.length() == 0) { filterStrBuilder.append("("); } else { filterStrBuilder.append(LOGIC_OR + "("); } return this; } /** * 添加右括号 * * @return */ public FilterRuleBuilder right() { filterStrBuilder.append(")"); return this; } /** * 列表查询字段 * * @param fieldKeys * @return */ public FilterRuleBuilder select(List<String> fieldKeys) { this.fieldKeys = fieldKeys; return this; } /** * 查询具体类的所有字段 * * @param cls * @return */ public FilterRuleBuilder selectAllFiled(Class cls) { Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { String fieldName = SFunctionParse.convertField(cls, field.getName()); select(fieldName); } return this; } /** * 添加查询字段 * * @param fieldKey * @return */ public FilterRuleBuilder select(String fieldKey) { fieldKeys.add(fieldKey); return this; } /** * 添加多个查询字段 * * @param fieldKeys * @return */ public FilterRuleBuilder select(String... fieldKeys) { for (String fieldKey : fieldKeys) { select(fieldKey); } return this; } /** * 多字段排序 * * @param fieldNames * @return */ public FilterRuleBuilder orderBy(boolean isDesc, String... fieldNames) { // 不为空加逻辑关系 if (orderBuilder.length() != 0) { orderBuilder.append(","); } for (String fieldName : fieldNames) { if (isDesc) { orderBuilder.append(String.format("%s DESC,", fieldName)); } else { orderBuilder.append(String.format("%s ASC,", fieldName)); } } // 删除最后一个字符 orderBuilder.deleteCharAt(orderBuilder.length() - 1); return this; } /** * 正序排序 * * @param fieldName * @return */ public FilterRuleBuilder orderByAsc(String fieldName) { // 不为空加逻辑关系 if (orderBuilder.length() != 0) { orderBuilder.append(","); } orderBuilder.append(String.format("%s ASC", fieldName)); return this; } /** * 倒序排序 * * @param fieldName * @return */ public FilterRuleBuilder orderByDesc(String fieldName) { // 不为空加逻辑关系 if (orderBuilder.length() != 0) { orderBuilder.append(","); } orderBuilder.append(String.format("%s DESC", fieldName)); return this; } /** * 等于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder eq(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s = '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s = %s)", fieldName, value)); } return this; } /** * 不等于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder ne(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s <> '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s <> %s)", fieldName, value)); } return this; } /** * 小于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder lt(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s < '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s < %s)", fieldName, value)); } return this; } /** * 大于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder gt(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s > '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s > %s)", fieldName, value)); } return this; } /** * 小于等于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder le(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s <= '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s <= %s)", fieldName, value)); } return this; } /** * 大于等于构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder ge(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append(String.format("(%s >= '%s')", fieldName, value)); } else { filterStrBuilder.append(String.format("(%s >= %s)", fieldName, value)); } return this; } /** * 模糊=构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder like(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append("(" + fieldName + " LIKE '%" + value + "%')"); } return this; } /** * 模糊<>构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder notLike(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append("(" + fieldName + " NOT LIKE '%" + value + "%')"); } return this; } /** * 模糊Left构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder likeLeft(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append("(" + fieldName + " LIKE '%" + value + "')"); } return this; } /** * 模糊Right构造 * * @param fieldName * @param value * @return */ public FilterRuleBuilder likeRight(String fieldName, Object value) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (value instanceof String || value instanceof Date) { filterStrBuilder.append("(" + fieldName + " LIKE '" + value + "%')"); } return this; } /** * between 连接 * * @param fieldName * @param startVal * @param endVal * @return */ public FilterRuleBuilder between(String fieldName, Object startVal, Object endVal) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (startVal instanceof String || startVal instanceof Date) { filterStrBuilder.append(String.format("(%s BETWEEN '%s'", fieldName, startVal)); } else { filterStrBuilder.append(String.format("(%s BETWEEN %s", fieldName, startVal)); } if (endVal instanceof String || endVal instanceof Date) { filterStrBuilder.append(String.format(" AND '%s')", endVal)); } else { filterStrBuilder.append(String.format(" AND '%s')", endVal)); } return this; } /** * netBetween 连接 * * @param fieldName * @param startVal * @param endVal * @return */ public FilterRuleBuilder notBetween(String fieldName, Object startVal, Object endVal) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } // 字母或数字要加引号 if (startVal instanceof String || startVal instanceof Date) { filterStrBuilder.append(String.format("(%s NOT BETWEEN '%s'", fieldName, startVal)); } else { filterStrBuilder.append(String.format("(%s NOT BETWEEN %s", fieldName, startVal)); } if (endVal instanceof String || endVal instanceof Date) { filterStrBuilder.append(String.format(" AND '%s')", endVal)); } else { filterStrBuilder.append(String.format(" AND '%s')", endVal)); } return this; } /** * 为空构造 * * @param fieldName * @return */ public FilterRuleBuilder isNull(String fieldName) { /// 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } filterStrBuilder.append(String.format("(%s IS NULL)", fieldName)); return this; } /** * 不为空构造 * * @param fieldName * @return */ public FilterRuleBuilder isNotNull(String fieldName) { // 不为空加逻辑关系,或者前面为左括号不加 if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') { filterStrBuilder.append(logic); } filterStrBuilder.append(String.format("(%s IS NOT NULL)", fieldName)); return this; } /** * 构建查询字段 * * @return */ public String buildFieldKeys() { return String.join(",", fieldKeys); } /** * 总行数 * * @param topRowCount * @return */ public FilterRuleBuilder topRowCount(int topRowCount) { this.TopRowCount = topRowCount; return this; } /** * 起始行数 * * @param startRow * @return */ public FilterRuleBuilder startRow(int startRow) { this.StartRow = startRow; return this; } /** * 最大行数,不可超过2000 * * @param limit * @return */ public FilterRuleBuilder limit(int limit) { if (limit < 2000) { this.Limit = limit; } else { this.Limit = 2000; } return this; } /** * 构造查询条件 * * @return */ @Override public String buildFilter() { if (filterStrBuilder.length() != 0) { return this.filterStrBuilder.toString(); } else { return ""; } } /** * 构造排序条件 * * @return */ @Override public String buildOrder() { if (orderBuilder.length() != 0) { return this.orderBuilder.toString(); } else { return ""; } } /** * 构建总行数 * * @return */ @Override public int buildTopRowCount() { return this.TopRowCount; } /** * 构建起始行数 * * @return */ @Override public int buildStartRow() { return this.StartRow; } /** * 构建最大行数 * * @return */ @Override public int buildLimit() { return this.Limit; } }
3.3 Builder类
import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; /** * @Author * @Date 2022/5/14 8:35 * @Description 针对类的条件构造 */ public final class Builder<T> extends AbstractBuilder<T> { /** * 字段构建器,增强其功能 */ private FilterRuleBuilder ruleBuilder; /** * class类 */ private Class<T> cls; public Builder(Class<T> cls) { this.cls = cls; this.ruleBuilder = new FilterRuleBuilder(); } public Class<T> getObjClass() { return cls; } /** * 静态构造器 * * @param cls * @param <T> * @return */ public static final <T> Builder<T> builder(Class<T> cls) { return new Builder<>(cls); } public Builder<T> selectAll() { ruleBuilder.selectAllFiled(cls); return this; } public <R> Builder<T> select(SFunction<T, R>... fieldNames) { ruleBuilder.select(SFunctionParse.resolves(fieldNames)); return this; } /** * 该方法用于查询一个复合类型class, * 查询class的包含Object属性或者List属性字段 * * @return */ public Builder<T> selectAllGeneralField() { Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { Class<?> fieldType = field.getType(); // 是否为基本类型或数组 if (generalType.contains(fieldType.getName()) || fieldType.isArray()) { ruleBuilder.select(SFunctionParse.convertField(cls, field.getName())); } else if (fieldType == List.class) {// 列表类型 // 获取列表中的泛型 Type genericType = field.getGenericType(); // 获取类型Class if (genericType instanceof ParameterizedType) { ParameterizedType typeCls = (ParameterizedType) genericType; Class subGenericClass = (Class<?>) typeCls.getActualTypeArguments()[0]; Field[] subFields = subGenericClass.getDeclaredFields(); for (Field subField : subFields) { ruleBuilder.select(SFunctionParse.convertField(subGenericClass, subField.getName())); } } } } return this; } public <R> Builder<T> orderBy(boolean isDesc, SFunction<T, R>... fieldNames) { ruleBuilder.orderBy(isDesc, SFunctionParse.resolves(fieldNames)); return this; } public <R> Builder<T> orderByAsc(SFunction<T, R> fieldName) { ruleBuilder.orderByAsc(SFunctionParse.resolve(fieldName)); return this; } public <R> Builder<T> orderByDesc(SFunction<T, R> fieldName) { ruleBuilder.orderByDesc(SFunctionParse.resolve(fieldName)); return this; } public <R> Builder<T> eq(SFunction<T, R> fieldName, Object value) { ruleBuilder.eq(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> ne(SFunction<T, R> fieldName, Object value) { ruleBuilder.ne(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> lt(SFunction<T, R> fieldName, Object value) { ruleBuilder.lt(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> gt(SFunction<T, R> fieldName, Object value) { ruleBuilder.gt(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> le(SFunction<T, R> fieldName, Object value) { ruleBuilder.le(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> ge(SFunction<T, R> fieldName, Object value) { ruleBuilder.ge(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> like(SFunction<T, R> fieldName, Object value) { ruleBuilder.like(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> notLike(SFunction<T, R> fieldName, Object value) { ruleBuilder.notLike(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> likeLeft(SFunction<T, R> fieldName, Object value) { ruleBuilder.likeLeft(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> likeRight(SFunction<T, R> fieldName, Object value) { ruleBuilder.likeRight(SFunctionParse.resolve(fieldName), value); return this; } public <R> Builder<T> between(SFunction<T, R> fieldName, Object startVal, Object endVal) { ruleBuilder.between(SFunctionParse.resolve(fieldName), startVal, endVal); return this; } public <R> Builder<T> notBetween(SFunction<T, R> fieldName, Object startVal, Object endVal) { ruleBuilder.notBetween(SFunctionParse.resolve(fieldName), startVal, endVal); return this; } public <R> Builder<T> isNull(SFunction<T, R> fieldName) { ruleBuilder.isNull(SFunctionParse.resolve(fieldName)); return this; } public <R> Builder<T> isNotNull(SFunction<T, R> fieldName) { ruleBuilder.isNotNull(SFunctionParse.resolve(fieldName)); return this; } public Builder<T> switchAND() { ruleBuilder.switchAND(); return this; } public Builder<T> switchOR() { ruleBuilder.switchOR(); return this; } /** * 添加and左括号 * * @return */ public Builder<T> andLeft() { ruleBuilder.andLeft(); return this; } /** * 添加or左括号 * * @return */ public Builder<T> orLeft() { ruleBuilder.orLeft(); return this; } /** * 添加右括号 * * @return */ public Builder<T> right() { ruleBuilder.right(); return this; } public Builder<T> topRowCount(int topRowCount) { ruleBuilder.topRowCount(topRowCount); return this; } public Builder<T> startRow(int startRow) { ruleBuilder.startRow(startRow); return this; } public Builder<T> limit(int limit) { ruleBuilder.limit(limit); return this; } @Override public List<String> getFieldKeys() { return ruleBuilder.getFieldKeys(); } /** * 如果没有设置查询字段,默认查询所有 * @return */ @Override public String buildFieldKeys() { if(fieldKeys.size() == 0){ selectAll(); } return ruleBuilder.buildFieldKeys(); } @Override public String buildFilter() { return ruleBuilder.buildFilter(); } @Override public String buildOrder() { return ruleBuilder.buildOrder(); } @Override public int buildTopRowCount() { return ruleBuilder.buildTopRowCount(); } @Override public int buildStartRow() { return ruleBuilder.buildStartRow(); } @Override public int buildLimit() { return ruleBuilder.buildLimit(); } }
3.4 ConvertType枚举
/** * @Author * @Date 2022/5/28 10:15 * @Description 转换类型 将_转换为.的类型 */ public enum ConvertType { /** * 全部转换 */ ALL, /** * 全部不转换 */ NO_ALL, /** * 转换最后一个 */ Last, // ============================以下真实场景没意义==================================== /** * 转换第一个 */ FIRST, /** * 不转换第一个 */ NO_FIRST, /** * 不转换最后一个 */ NO_LAST, }
3.5 SymbolConvert注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author * @Date 2022/5/28 10:09 * @Description 符号转换值 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface SymbolConvert { /** * 默认全部转换 * @return */ ConvertType value() default ConvertType.ALL; }
3.6 FormId注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author * @Date 2022/5/16 10:32 * @Description 查询表单Id,如不写,默认为类名 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface FormId { String value() default ""; }
3.7 K3Const常量类
/** * @Author * @Date 2022/7/20 9:40 * @Description K3使用的静态常量 */ public final class K3Const { public static final String ENABLE = "A"; public static final String DISABLE = "B"; }
3.8 SFunction接口
import java.io.Serializable; import java.util.function.Function; /** * @Author * @Date 2022/5/14 08:33 * @Description 序列化函数式接口 */ @FunctionalInterface public interface SFunction<T, R> extends Function<T, R>, Serializable { }
3.9 SFunctionParse类
import java.lang.invoke.SerializedLambda; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @Author * @Date 2022/5/16 8:45 * @Description TODO */ public final class SFunctionParse { /** * java属性转K3查询字段 * 将属性中的_符号转. * * @param cls 属性存在的类 * @param attr * @return */ public final static <T> String convertField(Class<T> cls, String attr) { try { // 没有类,全部转换 if (cls == null) { return attr.replace("_", "."); } // 获取字段 Field field = cls.getDeclaredField(attr); // 获取属性的符号转换注解 SymbolConvert symbolConvert = field.getAnnotation(SymbolConvert.class); // 不存在全部转换 if (symbolConvert == null) { return attr.replace("_", "."); } ConvertType type = symbolConvert.value(); String[] strings = attr.split("_"); StringBuilder builder = new StringBuilder(); int length = strings.length; // 存在判断 switch (type) { case ALL: // 所有都转 return attr.replace("_", "."); case NO_ALL: // 所有都不转 return attr; case Last: for (int i = 0; i < length - 1; i++) { builder.append(strings[i]).append("_"); } // 最后一个转 builder.deleteCharAt(builder.length() - 1).append("." + strings[length - 1]); return builder.toString(); case NO_FIRST: // 第一个不转 builder.append(strings[0] + "_"); // 其余都转 for (int i = 1; i < length; i++) { builder.append(strings[i] + "."); } builder.deleteCharAt(builder.length() - 1); return builder.toString(); case NO_LAST: // 其余转 for (int i = 0; i < length - 1; i++) { builder.append(strings[i] + "."); } // 最后一个不转 builder.deleteCharAt(builder.length() - 1).append("_" + strings[length - 1]); return builder.toString(); case FIRST: // 第一个转 builder.append(strings[0] + "."); // 其余不转 for (int i = 1; i < length; i++) { builder.append(strings[i] + "_"); } builder.deleteCharAt(builder.length() - 1); return builder.toString(); } } catch (Exception e) { e.printStackTrace(); } return ""; } /** * K3查询字段转java属性,字段不能包含. ,必须全转 * 将属性中的.符号转_ * * @param field * @return */ public final static <T> String convertAttr(String field) { return field.replace(".", "_"); } /** * 解析多个表达式 * * @param functions * @param convertPoint 是否将字段名中的_转换为点 * @param <R> * @return * @throws Exception */ public static final <T, R> String[] resolves(Boolean convertPoint, SFunction<T, R>... functions) { String[] fileNames = new String[functions.length]; String fileName; try { for (int i = 0; i < functions.length; i++) { SFunction<T, R> function = functions[i]; // 直接调用writeReplace Method methods = function.getClass().getDeclaredMethod("writeReplace"); methods.setAccessible(true); //反射调用 Object sl = methods.invoke(function); SerializedLambda serializedLambda = (SerializedLambda) sl; // 获取类 String implClass = serializedLambda.getImplClass(); Class<?> aClass = Class.forName(implClass.replace("/", ".")); // 获取方法名 String methodName = serializedLambda.getImplMethodName(); String name = methodName.replace("get", ""); // 首字母大写 fileName = name.substring(0, 1) + name.substring(1); if (convertPoint) { // 将_替换为.改成查询字段 fileName = convertField(aClass, fileName); } fileNames[i] = fileName; } } catch (Exception e) { e.printStackTrace(); } return fileNames; } /** * 解析多个表达式, 默认将字段名的_转为. * * @param functions * @param <R> * @return * @throws Exception */ public static final <T, R> String[] resolves(SFunction<T, R>... functions) { return resolves(true, functions); } /** * 解析一个表达式 * * @param function * @param convertPoint 是否将字段名的下划线转为点 * @param <R> * @return * @throws Exception */ public static final <T, R> String resolve(Boolean convertPoint, SFunction<T, R> function) { return resolves(convertPoint, function)[0]; } /** * 解析一个表达式 ,默认将字段名的_转为. * * @param function * @param <R> * @return * @throws Exception */ public static final <T, R> String resolve(SFunction<T, R> function) { return resolve(true, function); } }
3.10 K3Api类
import com.google.gson.internal.LinkedTreeMap; import com.kingdee.bos.webapi.entity.QueryParam; import com.kingdee.bos.webapi.sdk.K3CloudApi; import com.kingdee.bos.webapi.utils.CfgUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.SessionScope; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.text.SimpleDateFormat; import java.util.*; /** * @Author 张港 * @Date 2022/5/11 14:29 * @Description 金蝶数据接口工具类 */ @Component @ComponentScan("com.hpmont.scan.util.K3") @SessionScope // 防止多用户请求,字段混乱问题 public class K3Api { private final Logger log = LoggerFactory.getLogger(K3Api.class); /** * K3Cloud对象 */ private final K3CloudApi api; /** * 当次查询字段 */ private List<String> fieldKeys; /** * SDK方法中获取路径为项目根目录。 * 反射修改配置文件路径为空,改变配置文件的获取方式为流获取。 * 改成从项目中jar包读取。隐藏配置文件 */ public K3Api() { try { Class<CfgUtil> cls = CfgUtil.class; Method method = cls.getDeclaredMethod("setCfgFilePath", String.class); method.setAccessible(true); method.invoke(null,""); } catch (Exception e) { e.printStackTrace(); } api = new K3CloudApi(); } /** * 解析类上的注解FormId,获取表单Id * * @param cls * @param <T> * @return 存在返回FormId,不存在返回空字符 */ public <T> String getFormId(Class<T> cls) { if(cls == null){ return ""; } FormId formId = cls.getDeclaredAnnotation(FormId.class); if (formId != null) { return formId.value(); } else { // 不存在获取类名 String[] strings = cls.getName().split("\\."); return strings[strings.length-1]; } } /** * 获取字段的值 * * @param filedName 字段名称 * @param obj 对象 * @return */ private final Object getFieldValue(String filedName, Object obj) { try { Class<?> objCls = obj.getClass(); String firstLetter = filedName.substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + filedName.substring(1); Method method = objCls.getMethod(getter, new Class[]{}); Object value = method.invoke(obj, new Object[]{}); return value; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 检测查询结果是否异常 * 错误结果封装格式为: list中包含 * * @param result * @return */ public void checkException(List<List<Object>> result) { if(result == null){ throw new CustomException(ErrCode.ERROR_0,"K3连接异常"); } // 返回结果为1条记录,可能为错误信息 if (result.size() != 1) { return; } List<Object> objList = result.get(0); // 每条记录仅一个字段,有可能为错误信息 if (objList.size() != 1) { return; } Object resultObj = objList.get(0); // 错误信息的结果为LinkedTreeMap if (!(resultObj instanceof LinkedTreeMap)) { return; } LinkedTreeMap resultMap1 = (LinkedTreeMap) resultObj; // 获取一个叫Result的属性 Object resultObj2 = resultMap1.get("Result"); if (!(resultObj2 instanceof LinkedTreeMap)) { return; } LinkedTreeMap resultMap2 = (LinkedTreeMap) resultObj2; // 获取一个ResponseStatus的属性 Object respStatusObj = resultMap2.get("ResponseStatus"); if (!(respStatusObj instanceof LinkedTreeMap)) { return; } /** * respStatus为一个响应结果对象 * { * ErrorCode: Integer, * IsSuccess: Boolean, * Errors: ArrayList, * SuccessEntitys: ArrayList, * SuccessMessages: ArrayList, * MsgCode: Integer, * } */ LinkedTreeMap respStatus = (LinkedTreeMap) respStatusObj; Boolean isSuccess = (Boolean) respStatus.get("IsSuccess"); // 响应成功 if (isSuccess) { return; } StringBuffer errorMsg = new StringBuffer("K3友情提示:"); // 拼接错误消息 List<LinkedTreeMap> errorList = (List<LinkedTreeMap>) respStatus.get("Errors"); errorList.forEach(error -> errorMsg.append((String) error.get("Message")).append(";")); errorMsg.deleteCharAt(errorMsg.length() - 1); // 获取错误码 共有0-13种可能 Integer msgCode = (Integer) respStatus.get("MsgCode"); switch (msgCode) { case 1: log.error("上下文丢失:{}",errorMsg.toString()); case 2: log.error("没有权限:{}",errorMsg.toString()); case 3: log.error("操作标识为空:{}",errorMsg.toString()); case 4: log.error("异常:{}",errorMsg.toString()); case 5: log.error("单据标识为空:{}",errorMsg.toString()); case 6: log.error("数据库操作失败:{}",errorMsg.toString()); case 7: log.error("许可错误:{}",errorMsg.toString()); case 8: log.error("参数错误:{}",errorMsg.toString()); case 9: log.error("指定字段/值不存在:{}",errorMsg.toString()); case 10: log.error("未找到对应数据:{}",errorMsg.toString()); case 11: log.error("验证失败:{}",errorMsg.toString()); case 12: log.error("不可操作:{}",errorMsg.toString()); case 13: log.error("网控冲突:{}",errorMsg.toString()); default: log.error("默认:{}",errorMsg.toString()); } } /** * 设置字段的值 * * @param filedName 字段名称 * @param value 字段值 * @param obj 对象 * @return */ private final void setFieldValue(String filedName, Object value, Object obj) { try { Class<?> objClass = obj.getClass(); Field field = objClass.getDeclaredField(filedName); String firstLetter = filedName.substring(0, 1).toUpperCase(); String setter = "set" + firstLetter + filedName.substring(1); Method method = objClass.getMethod(setter, field.getType()); // 日期格式如果值为字符换需要转换 if (field.getType() == Date.class && !(value instanceof Date)) { // 对标准时间处理 String d = value.toString().replace("T", " ").replace("Z", ""); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); method.invoke(obj, format.parse(d)); } else { method.invoke(obj, value); } } catch (Exception e) { } } /** * 主要用于查询列表中主键对象是否封装 * 判断列表中是否包含某个子段元素 * * @param list 查询列表 * @param fieldName 字段名 * @param value 值 * @param <T> * @return 返回该元素 */ private final <T> T containObj(List<T> list, String fieldName, Object value) { T t; for (T item : list) { Object oldValue = getFieldValue(fieldName, item); // 字段相同,表示录入同一对象 if (oldValue != null && oldValue.equals(value)) { t = item; return t; } } return null; } /** * 判断类中是否包含某个字段名 * * @param clsMap * @param fileName * @return 返回包含字段名的类型 */ private final String containClass(Map<String, Class> clsMap, String fileName) { Set<Map.Entry<String, Class>> entries = clsMap.entrySet(); Iterator<Map.Entry<String, Class>> iterator = entries.iterator(); while (iterator.hasNext()) { Map.Entry<String, Class> entry = iterator.next(); Field[] fields = entry.getValue().getDeclaredFields(); for (Field field : fields) { if (field.getName().equals(fileName)) { return entry.getKey(); } } } return null; } /** * 查询数据 : 此方法需要在cls上添加注解@FormId * * @param filter 类条件构建器 * @param <T> * @return List-T */ public <T> List<T> query(Builder<T> filter) throws Exception { Class<T> cls = filter.getObjClass(); String formId = getFormId(cls); return query(formId, filter, cls); } /** * 查询数据 * * @param formId 查询表单ID * @param filter 条件构建器 * @param cls 查询类 * @param <T> * @return List-T */ public <T> List<T> query(String formId, AbstractBuilder<T> filter, Class<T> cls) throws Exception { // 保存当前查询字段 fieldKeys = filter.getFieldKeys(); QueryParam queryParam = new QueryParam(); queryParam.setFormId(formId); queryParam.setFieldKeys(filter.buildFieldKeys()); queryParam.setFilterString(filter.buildFilter()); queryParam.setOrderString(filter.buildOrder()); queryParam.setTopRowCount(filter.buildTopRowCount()); queryParam.setStartRow(filter.buildStartRow()); queryParam.setLimit(filter.buildLimit()); // 打印日志 log.info("请求信息:FormId={};FieldKeys={};FilterString={};OrderString={};StartRow={};Limit={};TopRowCount={}", queryParam.getFormId(), queryParam.getFieldKeys(), queryParam.getFilterString(), queryParam.getOrderString(), queryParam.getStartRow(), queryParam.getLimit(), queryParam.getTopRowCount()); // 查询结果集 List<List<Object>> lists = api.executeBillQuery(queryParam.toJson()); // 查询校验返回结果是否正确 checkException(lists); // 封装结果集 List<T> resultList = new ArrayList<>(); lists.forEach(item -> { try { T result = cls.newInstance(); for (int i = 0; i < fieldKeys.size(); i++) { // 将所有字段中.替换为_ String fieldName = SFunctionParse.convertAttr(fieldKeys.get(i)); setFieldValue(fieldName, item.get(i), result); } resultList.add(result); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }); return resultList; } /** * 查询数据 * * @param formId 查询表单ID * @param fieldKeys 查询字段 * @param cls 封装类 * @param <T> * @return List-T */ public <T> List<T> query(String formId, List<String> fieldKeys, Class<T> cls) throws Exception { FilterRuleBuilder builder = new FilterRuleBuilder(); builder.select(fieldKeys); return query(formId, builder, cls); } /** * 查询数据 : 此方法需要在cls上添加注解@FormId * * @param fieldKeys 查询字段 * @param cls 封装类 * @param <T> * @return List-T */ public <T> List<T> query(List<String> fieldKeys, Class<T> cls) throws Exception { String formId = getFormId(cls); FilterRuleBuilder builder = new FilterRuleBuilder(); builder.select(fieldKeys); return query(formId, builder, cls); } /** * 查询数据 * * @param formId 查询表单ID * @param filter 条件查询构造器 * @return List-List<Object> */ public List<List<Object>> query(String formId, AbstractBuilder filter) throws Exception { fieldKeys = filter.getFieldKeys(); QueryParam queryParam = new QueryParam(); queryParam.setFormId(formId).setFieldKeys(filter.buildFieldKeys()); queryParam.setFilterString(filter.buildFilter()); queryParam.setOrderString(filter.buildOrder()); queryParam.setTopRowCount(filter.buildTopRowCount()); queryParam.setLimit(filter.buildLimit()); queryParam.setStartRow(filter.buildStartRow()); // 打印日志 log.info("请求信息:FormId={};FieldKeys={};FilterString={};OrderString={};StartRow={};Limit={};TopRowCount={}", queryParam.getFormId(), queryParam.getFieldKeys(), queryParam.getFilterString(), queryParam.getOrderString(), queryParam.getStartRow(), queryParam.getLimit(), queryParam.getTopRowCount()); List<List<Object>> lists = api.executeBillQuery(queryParam.toJson()); checkException(lists); return lists; } /** * 查询数据 * * @param formId 查询表单ID * @param fieldKeys 查询字段 * @return List-Object */ public List<List<Object>> query(String formId, List<String> fieldKeys) throws Exception { FilterRuleBuilder builder = new FilterRuleBuilder(); builder.select(fieldKeys); return query(formId, builder); } /** * 查询一条数据 * * @param formId * @param filter 条件构建器 * @param <T> * @return 数据存在一条返回,不存在返回null,多条报错 */ public <T> T queryOne(String formId, Builder<T> filter) throws Exception { Class<T> cls = filter.getObjClass(); List<T> query = query(formId, filter, cls); int size = query.size(); if (size == 1) { return query.get(0); } else if (size == 0) { return null; } else { throw new RuntimeException("查询一条记录,但发现" + query.size() + "条数据"); } } /** * 查询一条数据 * * @param filter * @param <T> * @return 数据存在一条返回,不存在返回null,多条报错 */ public <T> T queryOne(Builder<T> filter) throws Exception { // 获取查询类 Class<T> cls = filter.getObjClass(); String formId = getFormId(cls); return queryOne(formId, filter); } /** * 查询一条数据 * * @param formId * @param filter * @return 数据存在一条返回,不存在返回null,多条报错 */ public List<Object> queryOne(String formId, AbstractBuilder filter) throws Exception { List<List<Object>> query = query(formId, filter); int size = query.size(); if (size == 1) { return query.get(0); } else if (size == 0) { return null; } else { throw new RuntimeException("查询一条记录,但发现" + query.size() + "条数据"); } } /** * 统计数量 * FilterRuleBuilder的查询字段不生效 * * @param formId * @return */ public Long count(String formId, AbstractBuilder filter) { List<List<Object>> query = null; try { QueryParam queryParam = new QueryParam(); queryParam.setFormId(formId); queryParam.setFieldKeys("count(1)"); if (filter != null) { queryParam.setFilterString(filter.buildFilter()); } query = api.executeBillQuery(queryParam.toJson()); } catch (Exception e) { e.printStackTrace(); } return Long.parseLong((String) query.get(0).get(0)); } /** * 统计数量 * * @param formId * @return */ public long count(String formId) { return count(formId, null); } /** * 结果映射: 除请求参数的属性外,其他字段自动映射 * * @param result 结果集 * @param cls 映射对象 * @param fieldId 主键Id * @param properties 映射对象中的映射字段,可以是对象或list,不支持数组 * 但是list只能有一个,因为映射最小单元是list的单位 * @param <T> 对象类型 * @return */ public <T> List<T> resultMap(List result, Class<T> cls, String fieldId, String... properties) { List<T> returnResult = new ArrayList<>(); try { // <T> 对象子对象A集合 Map<String, Class> subObjFields = new HashMap<>(); // <T> 对象的子列表对象集合 Map<String, Class> subListFields = new HashMap<>(); for (String property : properties) { Field field = cls.getDeclaredField(property); if (field.getType() == List.class) {// 列表先获取列表泛型的对象,然后获取对象的字段 // 获取列表中的泛型 Type genericType = field.getGenericType(); // 获取类型Class if (genericType instanceof ParameterizedType) { ParameterizedType typeCls = (ParameterizedType) genericType; Class subGenericClass = (Class<?>) typeCls.getActualTypeArguments()[0]; subListFields.put(property, subGenericClass); } } else if (!field.getType().isArray()) {// 对象直接获取对象的字段 Class subObjClass = cls.getDeclaredField(property).getType(); subObjFields.put(property, subObjClass); } } int size = result.size(); // 封装结果 for (int i = 0; i < size; i++) { Object obj = result.get(i); // obj是一个对象,根据对象封装 if (obj instanceof List) {// 列表类型的操作 List list = (List) obj; packByList(returnResult, list, cls, fieldId, subObjFields, subListFields); } else {// 对象类型的操作 packByObject(returnResult, obj, cls, fieldId, subObjFields, subListFields); } } } catch (Exception e) { e.printStackTrace(); } return returnResult; } /** * 结果映射: 除请求参数的属性外,其他字段自动映射 * * @param result 结果集 * @param cls 映射对象 * @param fieldId 主键Id * @param properties 映射对象中的映射字段,可以是对象或list, * 但是list只能有一个,因为映射最小单元是list的单位 * @param <T> 对象类型 * @return */ public <T, R> List<T> resultMap(List result, Class<T> cls, SFunction<T, R> fieldId, SFunction<T, R>... properties) { return resultMap(result, cls, SFunctionParse.resolve(false, fieldId), SFunctionParse.resolves(false, properties)); } /** * 包装List结果集,通常指没有第一次包装对象 * * @param returnResult 封装目标结果集 * @param list 封装源对象 * @param cls 目标对象 * @param fieldId 主键字段 * @param subObjFields 目标对象中的子对象 key: 属性名,value: 对象类 * @param subListFields 目标对象中的子列表,key: 属性名,value: 子列表中的Class类 * @param <T> * @return * @throws IllegalAccessException * @throws InstantiationException */ private <T> List<T> packByList(List<T> returnResult, List list, Class<T> cls, String fieldId, Map<String, Class> subObjFields, Map<String, Class> subListFields) throws IllegalAccessException, InstantiationException { // 字段个数 int size = list.size(); // 单元素对象 T t = null; Object subObj; // 子列表中对象 Object listObj = null; // 子列表 List<Object> subList; for (int j = 0; j < size; j++) { // 字段名,将点替换为字段 String fieldName = SFunctionParse.convertAttr(fieldKeys.get(j)); // 字段值 Object value = list.get(j); // 主键字段创建新对象 if (fieldName.equals(fieldId)) {// 主键字段赋值 // 获取对象或创建对象 t = containObj(returnResult, fieldName, value); // 同时添加到 if (t == null) { t = cls.newInstance(); setFieldValue(fieldName, value, t); // 创建新的对象并添加到结果集 returnResult.add(t); } } else { // 判断是否为子对象,返回子对象的属性名 String subFieldName = containClass(subObjFields, fieldName); // 获取子对象Class Class subCls = subObjFields.get(subFieldName); // 不为空表示在子对象中 if (subFieldName != null) { // 获取当前对象的子对象 subObj = getFieldValue(subFieldName, t); // 子对象为空,创建子对象 if (subObj == null) { subObj = subCls.newInstance(); } // 赋值子对象属性 setFieldValue(fieldName, value, subObj); // 赋值对象属性 setFieldValue(subFieldName, subObj, t); } else {// 不为子对象判断是否为子 // 判断是否为子列表 String subListFieldName = containClass(subListFields, fieldName); if (subListFieldName == null) {// 为空表示普通属性,自动封装 setFieldValue(fieldName, value, t); } else { // 查询对象是否包含子列表,不包含创建,包含赋值 subList = (List<Object>) getFieldValue(subListFieldName, t); if (subList == null) { // 并将列表添加在对象中 subList = new ArrayList<>(); setFieldValue(subListFieldName, subList, t); } // 列表中的子对象是否存在,不存在创建并添加在列表中 if (listObj == null) { // 获取子列表中的对象Class Class subListCls = subListFields.get(subListFieldName); listObj = subListCls.newInstance(); // 添加到子列表中 subList.add(listObj); } // 给列表对象赋值属性 setFieldValue(fieldName, value, listObj); } } // 给对象赋值,如果包装对象外也存在该属性,同样进行赋值 setFieldValue(fieldName, value, t); } } return returnResult; } /** * 根据对象包装结果集 * * @param returnResult 封装目标结果集 * @param obj 包装源对象 * @param cls 目标Class * @param fieldId 主键Id * @param subObjFields 目标对象中的子对象 key: 属性名,value: 对象类 * @param subListFields 目标对象中的子列表,key: 属性名,value: 子列表中的Class类 * @param <T> * @return * @throws IllegalAccessException * @throws InstantiationException */ private <T> List<T> packByObject(List<T> returnResult, Object obj, Class<T> cls, String fieldId, Map<String, Class> subObjFields, Map<String, Class> subListFields) throws IllegalAccessException, InstantiationException { Field[] resultFields = obj.getClass().getDeclaredFields(); // 单元素对象 T t = null; Object subObj; // 子列表中对象 Object listObj = null; // 子列表 List<Object> subList; for (int j = 0; j < resultFields.length; j++) { Field field = resultFields[j]; // 字段名 String fieldName = field.getName(); // 字段值 Object value = getFieldValue(fieldName, obj); // 主键字段创建新对象 if (fieldName.equals(fieldId)) {// 主键字段赋值 // 获取对象或创建对象 t = containObj(returnResult, fieldName, value); // 同时添加到 if (t == null) { t = cls.newInstance(); setFieldValue(fieldName, value, t); // 创建新的对象并添加到结果集 returnResult.add(t); } } else { // 判断是否为子对象,返回子对象的属性名 String subFieldName = containClass(subObjFields, fieldName); // 获取子对象Class Class subCls = subObjFields.get(subFieldName); // 不为空表示存在子对象中 if (subFieldName != null) { // 获取当前对象的子对象 subObj = getFieldValue(subFieldName, t); // 子对象为空,创建子对象 if (subObj == null) { subObj = subCls.newInstance(); } // 赋值子对象属性 setFieldValue(fieldName, value, subObj); // 赋值对象属性 setFieldValue(subFieldName, subObj, t); } else {// 不为子对象判断是否为子 // 判断是否为子列表 String subListFieldName = containClass(subListFields, fieldName); if (subListFieldName == null) {// 为空表示普通属性,自动封装 setFieldValue(fieldName, value, t); } else { // 查询对象是否包含子列表,不包含创建,包含赋值 subList = (List<Object>) getFieldValue(subListFieldName, t); if (subList == null) { // 并将列表添加在对象中 subList = new ArrayList<>(); setFieldValue(subListFieldName, subList, t); } // 列表中的子对象是否存在,不存在创建并添加在列表中 if (listObj == null) { // 获取子列表中的对象Class Class subListCls = subListFields.get(subListFieldName); listObj = subListCls.newInstance(); // 添加到子列表中 subList.add(listObj); } // 给列表对象赋值属性 setFieldValue(fieldName, value, listObj); } } // 给对象赋值,如果包装对象外也存在该属性,同样进行赋值 setFieldValue(fieldName, value, t); } } return returnResult; } /** * 查询并结果封装,自动识别复合类型封装 * * @param formId * @param filter 条件过滤器 * @param cls 封装类型 * @param fieldId 主键ID * @param <T> * @param <R> * @return */ public <T, R> List<T> queryAndResultMap(String formId, AbstractBuilder<T> filter, Class<T> cls, String fieldId) throws Exception { // 查询数据列表 List<List<Object>> result = query(formId, filter); // 获取复合类型字段 Field[] fields = cls.getDeclaredFields(); List<String> fieldNameList = new ArrayList<>(); for (Field field : fields) { // 判断字段是否为复杂类型,略过数组 if (!AbstractBuilder.generalType.contains(field.getType().getName()) && !field.getType().isArray()) { fieldNameList.add(field.getName()); } } return resultMap(result, cls, fieldId, fieldNameList.toArray(new String[]{})); } /** * 查询并结果封装,自动识别复合类型封装,此方法需要注解@FormId * * @param filter 条件过滤器 * @param fieldId 主键ID * @param <T> * @param <R> * @return */ public <T, R> List<T> queryAndResultMap(Builder<T> filter, SFunction<T, R> fieldId) throws Exception { Class<T> cls = filter.getObjClass(); String formId = getFormId(cls); // 查询数据列表 List<List<Object>> result = query(formId, filter); // 获取复合类型字段 Field[] fields = cls.getDeclaredFields(); List<String> fieldNameList = new ArrayList<>(); for (Field field : fields) { // 判断字段是否为复杂类型,略过数组 if (!AbstractBuilder.generalType.contains(field.getType().getName()) && !field.getType().isArray()) { fieldNameList.add(field.getName()); } } return resultMap(result, cls, SFunctionParse.resolve(fieldId), fieldNameList.toArray(new String[]{})); } }
-
使用示例: 提示: 实体类字段名最好与查询字段名一致,仅将.替换为_
@Data @NoArgsConstructor @AllArgsConstructor @FormId("BD_Customer") public class Customer { private long FCUSTID; private String FNumber; private String FName; private String FShortName; public static void main(String[] args) { // 1. 原始方式 K3CloudApi api = new K3CloudApi(); List<Customer> datas; try { QueryParam queryParam = new QueryParam(); queryParam.setFormId("BD_Customer") .setFieldKeys("fCUSTID,fNumber,fName,fCreateDate") .setFilterString("fCUSTID <= '***'"); datas = api.executeBillQuery(queryParam, Customer.class); datas.forEach(System.out::println); } catch (Exception e) { e.printStackTrace(); } // 2. 封装 FilterRuleBuilder后 K3Api k3Api = new K3Api(); FilterRuleBuilder builder = new FilterRuleBuilder(); builder.select("fCUSTID", "fNumber", "fName", "fCreateDate") .le("fCUSTID", "***"); List<Customer> customers = k3Api.query("BD_Customer", builder, Customer.class); customers.forEach(System.out::println); // 3. 封装 Builder后 List<Customer> customers1 = k3Api.query(Builder.builder(Customer.class) .select(Customer::getFCUSTID, Customer::getFName, Customer::getFCreateDate)); customers.forEach(System.out::println); /** * 4. k3Api还封装了queryOne,count方法。 * 5. query之后,数据可能需要映射,k3Api还封装了resultMap方法。 * resultMap的参数如下: 类比mybatis的结果映射 * @param result query的结果集 * @param cls 映射对象的类 * @param fieldId 对象主键Id * @param properties 需要映射的字段,可以是对象或list, * 但是list只能有一个,因为映射最小单元是list的单位 * 示例不介绍了。 */ } }
-
获取金蝶FomId:可通过administrator账号登录,在web api 测试功能中查看到。
-
获取金蝶字段名技巧:金蝶服务器地址可通过浏览器登录,与客户端效果一样,通过浏览器的审查单元格样式,可查看到属性data-field值即为查询字段。如下图所示: