在平时的项目开发中我们很容易碰到这样的问题;我们当实现一个业务接口时;需要到多张数据库表中取出所要的信息,一般情况下我们回选择在DDL层直接发起一条关联查询的sql将所需的字段关联查出来。最近公司的框架里引用另一种让开发者更方便的解决办法;相对我们通常的使用关联查询可能这种方法对查询性能稍稍若了点;先上代码。。。
/**
* step 1.反射类添加
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public abstract class DataRequiredReflect {
protected List<String[]> getNeedDetailMethod(Class dataClass,Class needDetailed) {
List<String[]> result = new ArrayList<String[]>();
while (dataClass != null) {
for (Field field : dataClass.getDeclaredFields()) {
if (needDetailed.isAssignableFrom(field.getType())) {
String methodNamePostfix = field.getName().substring(0, 1).toUpperCase()+ field.getName().substring(1);
String[] tmp = new String[2];
tmp[0] = "get" + methodNamePostfix;
tmp[1] = "set" + methodNamePostfix;
result.add(tmp);
}
}
dataClass = dataClass.getSuperclass();
}
return result;
}
protected Object[] getNeedDetailIds(List list, Class dataClass,Class needDetailed, List<String[]> detailMethodNames) {
Set<Object> result = new HashSet<Object>();
try {
List<Method> getMethods = new ArrayList<Method>();
for (String[] getSetName : detailMethodNames) {
Method getMethod = dataClass.getMethod(getSetName[0], null);
if (getMethod != null)
getMethods.add(getMethod);
}
if (getMethods.isEmpty())
return null;
Method getIdMethod = needDetailed.getMethod("getId", null);
for (Object obj : list) {
if(obj==null){
continue;
}
for (Method method : getMethods) {
Object detailedObj = method.invoke(obj, null);
if (detailedObj != null) {
Object tmpId = (Object) getIdMethod.invoke(detailedObj);
if (tmpId!=null)
result.add(tmpId);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result.toArray(new Object[0]);
}
protected String[] getNeedDetailStringIds(List list, Class dataClass,
Class needDetailed, List<String[]> detailMethodNames) {
Set<String> result = new HashSet<String>();
try {
List<Method> getMethods = new ArrayList<Method>();
for (String[] getSetName : detailMethodNames) {
Method setMethod = dataClass.getMethod(getSetName[0], null);
if (setMethod != null)
getMethods.add(setMethod);
}
if (getMethods.isEmpty())
return null;
Method getIdMethod = needDetailed.getMethod("getId", null);
if (getIdMethod != null)
for (Object obj : list) {
for (Method method : getMethods) {
Object propertyVal = method.invoke(obj, null);
if (propertyVal != null) {
Object idVal = getIdMethod.invoke(propertyVal);
if (idVal != null && !"0".equals(idVal))
result.add((String) idVal);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result.toArray(new String[0]);
}
@SuppressWarnings("unchecked")
protected void detailDatas(List list, Class dataClass, Map cachedDatas,
Class needDetailed, List<String[]> detailMethodNames) {
try {
if (detailMethodNames == null || detailMethodNames.isEmpty()
|| cachedDatas == null || cachedDatas.isEmpty()
|| list == null || list.isEmpty())
return;
Method getIdMethod = needDetailed.getMethod("getId", null);
if (getIdMethod != null)
for (Object obj : list) {
if(obj==null){
continue;
}
for (String[] getSetName : detailMethodNames) {
Method getMethod = dataClass.getMethod(getSetName[0],null);
Method setMethod = dataClass.getMethod(getSetName[1],needDetailed);
if (getMethod != null && setMethod != null) {
Object detailedObj = getMethod.invoke(obj, null);
if (detailedObj != null) {
Object datailedVal = cachedDatas.get(getIdMethod.invoke(detailedObj,new Object[]{}));
if(datailedVal==null){
datailedVal = cachedDatas.get(getIdMethod.invoke(detailedObj,new Object[]{})+"");
}
if (datailedVal != null)
setMethod.invoke(obj, datailedVal);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* shep 2填充主类的添加
*/
public class DataPopulateServiceImpl extends DataRequiredReflect implements DataPopulateService{
private MyBatisDAO myBatisDAO = null;//mybatis基类
private DataCacheService dataCacheService;
@Override
public void setObjectInfo(Object obj, Class fillClass, String searchStrId) {
if (obj == null)
return;
List list = new ArrayList();
list.add(obj);
setListInfos(list, fillClass, searchStrId);
}
@Override
public void setListInfos(List list, Class fillClass, String searchStrId) {
fillDataDetail(list, fillClass, searchStrId);
}
@Override
public void setObjectInfo(Object obj, String property, Class fillClass,String searchStrId) {
setObjectInfo(ObjectUtil.getNestedProperty(obj, property), fillClass,searchStrId);
}
@Override
public void setListInfos(List list, String property, Class fillClass,
String searchStrId) {
if (list == null || list.isEmpty()) {
return;
}
List objects = new ArrayList();
for (Object object : list) {
objects.add(ObjectUtil.getNestedProperty(object, property));
}
fillDataDetail(objects, fillClass, searchStrId);
}
protected Map findDataMapByIds(Object[] ids, String sqlMapId) {
Map result = new HashMap();
if (ids == null || ids.length == 0)
return result;
List list = myBatisDAO.findForList(sqlMapId, ids);
try {
for (Object obj : list) {
Long id = (Long) obj.getClass().getMethod("getId", null).invoke(obj, null);
result.put(id, obj);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private void fillDataDetail(List list, Class fillClass, String searchStr) {
if (list == null || list.isEmpty()) {
return;
}
Class dataClass = list.get(0).getClass();
List<String[]> detailMethodNames = super.getNeedDetailMethod(dataClass,fillClass);
Object[] ids = super.getNeedDetailIds(list, dataClass, fillClass,detailMethodNames);
Map map = dataCacheService.getDataMapByTypeKeys(fillClass, ids); //先从从缓存中查询
if(map==null || map.size()==0)
map = findDataMapByIds(ids, searchStr);
super.detailDatas(list, dataClass, map, fillClass, detailMethodNames);
}
public void setMyBatisDAO(MyBatisDAO myBatisDAO) {
this.myBatisDAO = myBatisDAO;
}
public MyBatisDAO getMyBatisDAO() {
return myBatisDAO;
}
public DataCacheService getDataCacheService() {
return dataCacheService;
}
public void setDataCacheService(DataCacheService dataCacheService) {
this.dataCacheService = dataCacheService;
}
}
public interface DataPopulateService {
/**
* 填兖单个对象的信息
*
* @param obj
* 需要被填充的对象
* @param fillClass
* 需要填充属性所属的类
* @param searchStrId
* 查询条件
* @throws WSMessage
*/
public void setObjectInfo(Object obj, Class fillClass, String searchStrId);
/**
* 批量填兖对象的信息
*
* @param list
* 需要被填充的对象
* @param fillClass
* 需要填充属性所属的类
* @param searchStrId
* 查询条件
* @throws WSMessage
*/
public void setListInfos(List list, Class fillClass, String searchStrId);
/**
* 根据属性填兖单个对象的信息
*
* @param obj
* 需要被填充的对象
* @param property
* 需要被填充的属性
* @param fillClass
* 需要填充属性所属的类
* @param searchStrId
* 查询条件
* @throws WSMessage
*/
public void setObjectInfo(Object obj, String property, Class fillClass,String searchStrId);
/**
* 根据属性批量填兖对象的信息
*
* @param list
* 需要被填充的对象
* @param property
* 需要被填充的属性
* @param fillClass
* 需要填充属性所属的类
* @param searchStrId
* 查询条件
*/
public void setListInfos(List list, String property, Class fillClass,String searchStrId);
}
/**
* shep 3.抽象的填充接口
*/
public abstract class AbstractDataPopulateDaoImpl implements DataPopulateDao{
@Autowired
public DataPopulateService dataPopulateService;
/**
* 获取In查询的sqlMapId
*
* @return
*/
public abstract String getFindInSqlMapId();//实现此抽象方法的dao返回selectId
@Override
public void setObjectInfo(Object obj, Class fillClass) {
dataPopulateService.setObjectInfo(obj, fillClass, getFindInSqlMapId());
}
@Override
public void setListInfos(List list, Class fillClass) {
dataPopulateService.setListInfos(list, fillClass, getFindInSqlMapId());
}
@Override
public void setObjectInfo(Object obj, String property, Class fillClass) {
dataPopulateService.setObjectInfo(obj, property, fillClass, getFindInSqlMapId());
}
@Override
public void setListInfos(List list, String property, Class fillClass) {
dataPopulateService.setListInfos(list, property, fillClass, getFindInSqlMapId());
}
}
public interface DataPopulateDao {
/**
* 填兖单个对象的信息
*
* @param obj
* 需要被填充的对象
*/
public void setObjectInfo(Object obj, Class fillClass);
/**
* 批量填兖对象的信息
*
* @param list
*/
public void setListInfos(List list, Class fillClass);
/**
* 根据属性填兖单个对象的信息
*
* @param obj
* 需要被填充的对象
*/
public void setObjectInfo(Object obj, String property, Class fillClass);
/**
* 根据属性批量填兖对象的信息
*
* @param list
* 需要被填充的对象
*/
public void setListInfos(List list, String property, Class fillClass);
}
**********************************************割一下********************************************************************
接下来这样调用:
POJO:
private DoctorServiceInfo doctorServiceInfo;
public class DoctorInfo {
public DoctorServiceInfo getDoctorServiceInfo() {
return doctorServiceInfo;
}
public void setDoctorServiceInfo(DoctorServiceInfo doctorServiceInfo) {
this.doctorServiceInfo = doctorServiceInfo;
}}
mybatis mappering:
<pre name="code" class="html"><pre name="code" class="java"><select id="findDoctorServiceInfoIn" resultMap="doctorServiceInfoMap">
SELECT <include refid="Base_Column_List" /> FROM doctor_service_info WHERE DOCTOR_ID IN
<foreach item="item" index="index" collection="array" open="(" separator="," close=")">
#{item}
</foreach>
</select>
DAO:
public interface DoctorServiceInfoDao extends DataPopulateDao{...}
@Repository("doctorServiceInfoDao")
public class DoctorServiceInfoDaoImpl extends AbstractDataPopulateDaoImpl implements DoctorServiceInfoDao {
<span style="white-space:pre"> </span>@Override
public String getFindInSqlMapId() {
return FIND_IN;
}
}
最后service调用:
doctorServiceInfoDao.setObjectInfo(doctor, DoctorServiceInfo.class);
搞定...