问题:
写SQL时难免会有一些需求要进行多张表关联才能查出来,但是进行多变查询的话,有又会造成查询效率严重下降,此时我们就需要拆分sql,拆分完可以显著提升查询效率,但此时我们每个sql查询的只是一部分数据,最后还需要将他们拼装到一起,传统的BeanUtil提供的copyProperties方法会将源数据的属性统统复制给目标对象这样不利于我们拼装sql,我们需要的只是非空的部分
思路:
copyProperties 方法的第三参数String... ignoreProperties(要忽略的属性),有了此种实现,我们就可以在数据拷贝之前拿到源数据的null值然后忽略就可以了详细请看getNullPropertyNames方法
有了这种还不算完,因为在拼装时还有很多情况查询的结果是一个集合,那么这种情况一般来说需要根据某一个字段来进行匹配,于是有了copyListPropertiesIgnoreNull方法,原理就是循环两个集合,首先循环source时通过反射获取到要匹配的字段,将其作为map的key,而这个对象就作为value,随后循环target利用反射获取到要匹配的字段从map中获取到前面放入的对象(map可以高效的索引到value),于是就可以利用前面封装好的copyPropertiesIgnoreNull方法拷贝非空的属性
/**
* 属性复制(不复制空属性)
*
* @author zzt
* @date 2022/08/20
*/
public class BeanNotNullUtil {
/**
* 获取到对象中属性为null的属性名
*
* @param source
* @return
*/
private static String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (ObjectUtils.isEmpty(srcValue)) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
/**
* 拷贝非空对象属性值
*
* @param source
* @param target
*/
public static void copyPropertiesIgnoreNull(Object source, Object target) {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}
/**
* 集合拷贝非空数据
*
* @param source 数据源
* @param target 目标
* @param propertyName 要匹配的属性名,例如两个集合使用id进行匹配拷贝 propertyName: "id"
*/
public static void copyListPropertiesIgnoreNull(List<?> source, List<?> target, String propertyName) {
if (CollectionUtils.isEmpty(source)) {
throw new NullPointerException("copyListPropertiesIgnoreNull source源数据为空!");
}
Map<Object, Object> map = new HashMap<>(source.size());
source.forEach(s -> {
final BeanWrapper sourceBean = new BeanWrapperImpl(s);
Object value = sourceBean.getPropertyValue(propertyName);
if (value == null) {
throw new NullPointerException("copyListPropertiesIgnoreNull获取参数异常");
}
map.put(value, s);
});
target.forEach(s -> {
final BeanWrapper targetBean = new BeanWrapperImpl(s);
Object value = targetBean.getPropertyValue(propertyName);
if (value == null) {
throw new NullPointerException("copyListPropertiesIgnoreNull获取参数异常");
}
Object o = map.get(value);
copyPropertiesIgnoreNull(o, s);
});
}
}
测试:
public static void main(String[] args) {
List<UserVo> vos1 = new ArrayList<>();
vos1.add(new UserVo().setName("张三")
.setId("1"));
vos1.add(new UserVo().setId("2")
.setName("李四"));
List<UserVo> vos2 = new ArrayList<>();
vos2.add(new UserVo().setId("1")
.setPassword("123456"));
vos2.add(new UserVo().setId("2")
.setPassword("654321"));
copyListPropertiesIgnoreNull(vos2, vos1,"id");
System.out.println(vos1);
//[UserVo(id=1, name=张三, password=123456), UserVo(id=2, name=李四, password=654321)]
}