1、使用Specification+JPA不作封装的时候每次都要挨个判断属性,很是麻烦
以下对生成Specification做一个封装
/**
* 生成全属性条件查询通用Specification
*
* @param tableMap 属性参数
* @param clazz 要查询的实体类或vo类
* @param excludeAttr 不使用模糊搜索的字符串属性
* @param map 外键关联查询
* @param <S>
* @return
*/
public <S> Specification<S> createSpecification(Map<String, String> tableMap, Class clazz, List<String> excludeAttr, Map map) {
Specification<S> specification = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
//未删除的数据
try {
clazz.getDeclaredField(Constants.VALID);
if (!StringUtils.isEmpty(tableMap.get(Constants.VALID))) {
predicates.add(cb.equal(root.get(Constants.VALID), Integer.valueOf(tableMap.get(Constants.VALID))));
} else {
predicates.add(cb.equal(root.get(Constants.VALID), 1));
}
} catch (NoSuchFieldException e) {
logger.warn("没有找到 {valid} 属性");
}
Field[] declaredFields = clazz.getDeclaredFields();
if (tableMap != null) {
for (Field field : declaredFields) {
String fieldName = field.getName();
if (!StringUtils.isEmpty(tableMap.get(fieldName))) {
String typeName = field.getGenericType().getTypeName();
Class<?> aClass = null;
try {
aClass = Class.forName(typeName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//属性不包含特定的属性并且是字符串采用模糊搜索
if (aClass == String.class && (CollectionUtils.isEmpty(excludeAttr) || !excludeAttr.contains(fieldName))) {
String queryFieldName = "%" + tableMap.get(fieldName).replace("/", "\\/")
.replaceAll("_", "\\\\_").replaceAll("%", "\\\\%") + "%";
predicates.add(cb.like(root.get(fieldName), queryFieldName));
} else {
predicates.add(cb.equal(root.get(fieldName), tableMap.get(fieldName)));
}
}
}
if (!CollectionUtils.isEmpty(map)) {
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String sourceKey = iterator.next().toString();
Map mapping = (Map) map.get(sourceKey);
Join join = root.join(sourceKey, JoinType.INNER);
Iterator mappingItr = mapping.keySet().iterator();
while (mappingItr.hasNext()) {
String joinKey = mappingItr.next().toString();
String joinAttr = mapping.get(joinKey).toString();
if (!StringUtils.isEmpty(tableMap.get(joinKey))) {
predicates.add(cb.equal(join.get(joinAttr), tableMap.get(joinKey)));
}
}
}
}
}
Predicate[] pre = new Predicate[predicates.size()];
Predicate preAnd = cb.and(predicates.toArray(pre));
return query.where(preAnd).getRestriction();
};
return specification;
}
2、使用方式
Map<String, Map<String, String>> joinAttr = new HashMap(4);
//mapping为请求参数与实体属性名之间的映射关系
Map mapping = new HashMap(4);
mapping.put("tankAreaId", "id");
mapping.put("tankAreaCode", "tankAreaCode");
//joinAttr为当前实体关联字段名称
joinAttr.put("tankArea", mapping);
Specification<TankMovementEntity> specification = reflectUtil.createSpecification(tableMap, TankMovementVo.class, null, createJoinField());