工作中,难免在重复的做一些事情,查询数据。eg:销售主订单sales_order, 销售子订单sales_sub_order,关系是一对多。当我们知道销售订单想要获取子订单的数据的获取方式:
一、初步设想方法:
批量获取销售子订单数据,往往是循环去调用数据库查询,eg:
for (SalesOrder salesOrder : salesOrders) {
List<SalesSubOrder> salesSubOrders = SalesSubOrderDao
.listSalesSubOrderByOrderNo(salesOrder.getSalesOrderNo());
}
这个时候,当查询的订单数据很大时,批量去查询子订单,调用查询子订单接口数量非常多,这个时候项目经理或者是业务部门的来找你麻烦了,“哎呀,什么破系统了,查个订单数据半天打不开...”
二、改进方法
既然批量调用查询数据库接口,那好吧,我不批量查询了,我汇总销售订单号,加入索引,批量去查询总可以了吧。调用一次总比你调用100次花时间少吧,于是乎我这样做了。
String[] orderNos = new String[salesOrders.size()];
int index = 0;
for (SalesOrder salesOrder : salesOrders) {
orderNos[index] = salesOrder.getOrderNo();
index ++;
}
return salesSubOrderDao.listSalesSubOrdersByOrderNos(orderNos);
这样是可以避免循环去DB查询数据的问题了,可是问题又来了,项目代码评审的时候,一看,我嚓,导出是这种组合某一个属性为数组的操作,都是差不多一个模样,能不能提炼出来,一句代码搞定?
三、再次改进
当你觉得不合理或者不爽的时候,我就想着去改进一下,一句代码搞定,答案是可以的。
salesSubOrderDao.listSalesSubOrdersByOrderNos(
new ListConvertAdapter<String, SalesChangeOrder>(
salesOrders, ListConvertAdapter.CommonPropertyAware.order_no)
.getElements());
初步设想是这样的,比老是循环去组装数组看得爽点。。。
优化待续,下面是获取类某一属性集合的实现,代码如下:
package com.hqb360.common.lang;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 功能描述:List转换获取参数值适配器
*
* @author: Zhenbin.Li
* Date: 13-11-3 Time:下午12:29
*/
public class ListConvertAdapter<T, V> {
/** 生成类属性对象List集合 */
private List<V> objects;
/** 需要生成List的类属性名称 */
private String propertyName;
/**
* 构造方法: 适配器在创建时,必须传List参数和生成属性名称
*
* @param objects List集合
* @param propertyName 需要生成List的类属性名称
*/
public ListConvertAdapter(List<V> objects, String propertyName) {
this.objects = objects;
this.propertyName = propertyName;
if (!validConvertParams()) {
throw new RuntimeException("传入参数为空,objects=" + objects + ", propertyName=" + propertyName);
}
}
/**
* List集合对象的某一个属性转换为Object[]集合
*
* <p>获取属性list去重复,返回数组</p>
* @return
*/
public Object[] getUnRepeatElementsArray() {
Set<T> objectPropertyElements = getUnRepeatElements();
if (CollectionUtil.isEmpty(objectPropertyElements)) {
return null;
}
return objectPropertyElements.toArray();
}
/**
* List集合对象的某一个属性转换为Set集合
*
* <p>获取属性list去重复,返回HashSet</p>
* @return
*/
public Set<T> getUnRepeatElements() {
List<T> objectPropertyElements = getElements();
if (CollectionUtil.isEmpty(objectPropertyElements)) {
return new HashSet<T>(0);
}
Set<T> objectPropertyElementSet = Sets.newHashSet();
for (T objectPropertyElement : objectPropertyElements) {
objectPropertyElementSet.add(objectPropertyElement);
}
return objectPropertyElementSet;
}
/**
* List集合对象的某一个属性转换为Object[]集合
*
* @return
*/
public Object[] getElementsArray() {
List<T> objectPropertyElements = getElements();
if (CollectionUtil.isEmpty(objectPropertyElements)) {
return null;
}
return objectPropertyElements.toArray();
}
/**
* List集合对象的某一个属性转换为List集合
*
* <p>获取属性list不去重复,返回ArrayList</p>
* @return
*/
@SuppressWarnings("unchecked")
public List<T> getElements() {
List<T> objectPropertyElements = Lists.newArrayList();
for (V v : objects) {
Class<?> clazz = v.getClass();
// 查询属性在类中存不存在
// private方法查询
Field field = null;
try {
field = clazz.getDeclaredField(propertyName);
}
catch (NoSuchFieldException e) {
}
// 查询不到找public方法
if (field == null) {
try {
field = clazz.getField(propertyName);
}
catch (NoSuchFieldException e) {
}
}
// 还是为空直接返回
if (field == null) {
return getEmptyValues();
}
// 获取方法名称
StringBuffer nameBuffer = new StringBuffer();
nameBuffer.append(ElementsMethod.GET.getMethodHeadCode()).append(propertyName);
// 找出对应方法
Method getPropertyNameMethod = null;
Method[] methods = clazz.getMethods();
if (ArrayUtil.isEmpty(methods)) {
return getEmptyValues();
}
for (Method method : methods) {
if (method.getName().toUpperCase().equals(nameBuffer.toString().toUpperCase())) {
getPropertyNameMethod = method;
break;
}
}
// 找不到对应属性的GET方法
if (getPropertyNameMethod == null) {
return getEmptyValues();
}
try {
objectPropertyElements.add((T)getPropertyNameMethod.invoke(v));
}
catch (IllegalAccessException ex) {
return getEmptyValues();
}
catch (InvocationTargetException ex) {
return getEmptyValues();
}
}
return objectPropertyElements;
}
/**
* 验证需要转换参数是否符合转换逻辑
*
* @return
*/
protected boolean validConvertParams() {
// 属性名称为空
if (StringUtil.isBlank(propertyName)) {
return false;
}
// 传入参数集合为空直接返回空list
if (CollectionUtil.isEmpty(objects)) {
return false;
}
for (V object : objects) {
if (object == null) {
return false;
}
}
return true;
}
/**
* 验证不符合逻辑时,返回空List
*
* @return
*/
private List<T> getEmptyValues() {
return new ArrayList<T>(0);
}
/**
* 常用获取数组常量,参数取值可以扩展
*/
protected interface CommonPropertyAware {
public static final String id = "id";
public static final String cid = "cid";
public static final String SPU_ID = "spuId";
public static final String SKU_ID = "skuId";
public static final String sku_name = "skuName";
public static final String order_no = "orderNo";
}
/**
* 类属性方法Head枚举
*/
protected enum ElementsMethod {
/** get方法 */
GET("get"),
/** boolean方法 */
IS("is"),
/** set方法 */
SET("set");
/** 方法头参数 */
private String methodHeadCode;
/**
* 构造方法
*
* @param methodHeadCode
*/
private ElementsMethod(String methodHeadCode) {
this.methodHeadCode = methodHeadCode;
}
/**
* 获取方法Head枚举
*
* @return
*/
private String getMethodHeadCode() {
return methodHeadCode;
}
}
}