发表于: 2017-07-12 22:26:22

4 1327


今天完成的任务:

       修复bug的时候,查日志的时候,发现log.info输出的日志和代码中的实际执行不符.查了一圈,反而学到了好多dal层的东西.

首先是场景:这是昨天出bug的一个方法,红色是出问题的地方

@RequestMapping(value = "/a/u/venderTask/search", method = RequestMethod.GET)
public String getVenderTaskList(HttpServletRequest request, HttpServletResponse response, ModelMap model, Long id,
     String distributorShortName, String teamName, Long minCreateAt, Long maxCreateAt, Long minPlanBeginAt,
     Long maxPlanBeginAt, Integer status, String sortField, String sort, Integer page, Integer size) {
log.info("controller getVenderTaskList begin...");
log.info("arguments: id = [" + id + "], distributorShortName = [" + distributorShortName + "], teamName = ["
        + teamName + "], minCreateAt = [" + minCreateAt + "], maxCreateAt = [" + maxCreateAt
        + "], minPlanBeginAt = [" + minPlanBeginAt + "], maxPlanBeginAt = [" + maxPlanBeginAt + "], status = ["
        + status + "]");
log.info("sort arguments: sortField = [" + sortField + "], sort = [" + sort + "]");
log.info("paging arguments: page = [" + page + "], size = [" + size + "]");
if (StringUtils.isEmpty(sortField)) {
     sortField = "id";
  } else {
     sortField = reflectToDBMap.get(sortField);
  }
if (StringUtils.isEmpty(sort)) {
     sort = "desc";
  }
if (page == null) {
     page = 1;
  }
if (size == null) {
     size = 10;

  }

//搜索的时候,传入的参数会因为第几页而变化,红色的是原来的方法,会造成遗漏数据表中前面记录的情况

//第一种修改方法是:int start=0,(直接赋值,让sql语句从第零条记录开始查询)

//第二种修改方法是:在前端在传参的时候,如果是搜索接口,page=1.

int start = (page - 1) * size, total = 0, totalPage = 0;
try {
/* 第一步、判断当前账号是厂家还是第三方 */
     Manager manager = (Manager) request.getAttribute("manager");
     Map<String, Vender> accountMap = auditCommonService.judgeCurrentManager(manager);
log.info("accountMap is: " + accountMap);
     Set<Entry<String, Vender>> entry = accountMap.entrySet();
     String key = null;
     Vender vender = null;
for (Entry<String, Vender> e : entry) {
        key = e.getKey();
        vender = e.getValue();
     }

/* 第二步、不同账号获取不同厂家任务id */
     List<VenderTask> venderTasks = new ArrayList<>();
     Long venderId; // 作为搜索厂家任务列表的条件
     if (Manager.IS_THIRD_PARTY.equals(key)) { // 第三方账号
        log.info("key is third party");
        venderId = null;
     } else if (Manager.IS_VENDER.equals(key)) { // 厂家账号未禁用
        log.info("key is vender and not forbidden");
        venderId = vender.getId();
     } else { // 厂家账号被禁用
        log.info("key is forbidden");
        model.addAttribute("code", VenderTaskEnum.venderIsForbidden.getValue());
return "/data/json";
     }
     Map<String, Object> params = VenderTaskUtil.venderTaskList(id, distributorShortName, teamName, minCreateAt,

           maxCreateAt, minPlanBeginAt, maxPlanBeginAt, status, sortField, sort, venderId, false);

//这里上面传入的page,size转为动态sql语句的参数

     List<Long> ids = venderTaskService.getIdsByDynamicCondition(VenderTask.class, params, start, size);
log.info("ids is: " + ids);
     List<Map<String, Object>> result = new ArrayList<>();
if (CollectionUtils.isEmpty(ids)) {
log.info("ids is empty");
     } else {
        venderTasks = venderTaskService.getObjectsByIds(ids);
log.info("venderTasks size is: " + venderTasks.size());
/* 拿到每个厂家任务的外勤小红点和拍照小红点 */
        params = VenderTaskUtil.getRedIdsByVenderTaskIds(ids);
        List<Long> rmnIds = redMarkNumService.getIdsByDynamicCondition(RedMarkNum.class, params, 0,
              Integer.MAX_VALUE);
log.info("rmnIds is: " + rmnIds);
        List<RedMarkNum> rmns = redMarkNumService.getObjectsByIds(rmnIds);
log.info("rmns size is: " + rmns.size());
        Map<Long, RedMarkNum> redMap = CollectionConvertUtil.list2Map(rmns, "getVenderTaskId",
              RedMarkNum.class);
for (VenderTask vt : venderTasks) {
           RedMarkNum r = redMap.get(vt.getId());
           Map<String, Object> vtMap = BeanToMap.beanToMap2(vt);
           vtMap.put("memberNum", r.getMemberNum());
           vtMap.put("photoNum", r.getPhotoNum());
           result.add(vtMap);
        }
/* 计算总页数 */
        params = VenderTaskUtil.venderTaskList(id, distributorShortName, teamName, minCreateAt, maxCreateAt,
              minPlanBeginAt, maxPlanBeginAt, status, sortField, sort, venderId, true);
        BigInteger temp = (BigInteger) venderTaskService.getObjectByDynamicCondition(VenderTask.class, params,
0, 1);
        total = temp.intValue();
        totalPage = (total - 1) / size + 1;
     }

     model.addAttribute("page", page);
     model.addAttribute("size", size);
     model.addAttribute("total", total);
     model.addAttribute("totalPage", totalPage);
     model.addAttribute("venderTaskList", result);
     model.addAttribute("code", 0);
  } catch (Throwable t) {
log.error("getVenderTaskList error...", t);
     model.addAttribute("code", -1);
return "/data/json";
  }
log.info("controller getVenderTaskList end...");
return "/haichuan-audit-service/venderTask/json/venderTaskListJson";
}

通过下面接口第一个方法:

venderTaskService.getIdsByDynamicCondition
package com.ptteng.common.dao;

import com.gemantic.common.exception.ServiceDaoException;
import com.gemantic.common.exception.ServiceException;
import java.util.List;
import java.util.Map;

public interface BaseDaoService {
   List<Long> getIdsByDynamicCondition(Class var1, Map<String, Object> var2, Integer var3, Integer var4) throws ServiceException, ServiceDaoException;

   Object getObjectByDynamicCondition(Class var1, Map<String, Object> var2, Integer var3, Integer var4) throws ServiceException, ServiceDaoException;

boolean fakeDelete(Class var1, Long var2) throws ServiceException, ServiceDaoException;

void deleteList(Class var1, List<Long> var2) throws ServiceException, ServiceDaoException;
}

具体的实现类.这里只贴出来,我们要用到的第一个方法.

import com.gemantic.common.exception.ServiceDaoException;
import com.gemantic.common.exception.ServiceException;
import com.gemantic.dal.dao.Dao;
import com.gemantic.dal.dao.exception.DaoException;
import com.ptteng.common.dao.BaseDaoService;
import com.ptteng.common.dao.util.SQLUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.Table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BaseDaoServiceImpl implements BaseDaoService {
protected Dao dao;
private static final Log log = LogFactory.getLog(BaseDaoServiceImpl.class);

public BaseDaoServiceImpl() {
   }

public Dao getDao() {
return this.dao;
   }

public void setDao(Dao dao) {
       log.info("set dao " + dao);
this.dao = dao;
   }


//前面/a/u/venderTask/search接口中的参数在这里引入了.

public List<Long> getIdsByDynamicCondition(Class clz, Map<String, Object> conditions, Integer start, Integer limit) throws ServiceException, ServiceDaoException {
       String table = null;
       String sql = "";

       try {
           Annotation e = clz.getAnnotation(Table.class);
           Class ids = e.annotationType();
           Method method = ids.getDeclaredMethod("name", (Class[])null);
           table = (String)method.invoke(e, (Object[])null);
       } catch (Throwable var13) {
           var13.printStackTrace();
           log.error(clz + "  run dynamic  wrong " + conditions + " start " + start + " size " + limit);
       }

       try {

           //转成具体的sql语句,详细方法在下面贴出来

           sql = SQLUtil.convert2Sql(conditions, start, limit);
           Object e1 = this.dao.excuteSimpleSql(sql, clz);
           ArrayList ids1;
           if(!(e1 instanceof List)) {
               log.info(sql + " result is not list " + e1 + " instance " + e1.getClass());
               ids1 = new ArrayList();
               BigInteger id2 = (BigInteger)e1;
               ids1.add(Long.valueOf(id2.longValue()));
               return ids1;
           } else {
               log.info(sql + " result is list " + e1);
               ids1 = new ArrayList();
               Iterator id = ((List)e1).iterator();

               while(id.hasNext()) {
                   Object oo = id.next();
                   BigInteger id1 = (BigInteger)oo;
                   ids1.add(Long.valueOf(id1.longValue()));
               }

               return ids1;
           }
       } catch (DaoException var14) {
           log.error(" count by getPuserIds " + sql);
           log.error(var14);
           var14.printStackTrace();
           throw new ServiceDaoException(var14);
       }
   }


在这里转换成具体的sql语句.

public class SQLUtil {
private static final Log log = LogFactory.getLog(SQLUtil.class);

public SQLUtil() {
}

public static String convert2Sql(Map<String, Object> conditions, Integer start, Integer limit) {
StringBuffer sqlBuffer = new StringBuffer();
String querySentence;
boolean querySentence1;
if(conditions.containsKey("@update")) {
sqlBuffer = sqlBuffer.append("update ");
if(conditions.containsKey("@table")) {
querySentence = (String)conditions.get("@table");
sqlBuffer = sqlBuffer.append(querySentence);
} else {
log.error("not get any table ");
}

sqlBuffer = sqlBuffer.append(" set ");
querySentence1 = false;
String first;
if(conditions.containsKey("@field")) {
first = (String)conditions.get("@field");
sqlBuffer = sqlBuffer.append(first);
} else {
log.error("not get any field ");
}

sqlBuffer = sqlBuffer.append(" = ");
if(conditions.containsKey("@value")) {
first = (String)conditions.get("@value");
sqlBuffer = sqlBuffer.append(first);
} else {
log.error("not get any value ");
}

sqlBuffer = sqlBuffer.append(" where ");
boolean first1 = true;
Iterator field = conditions.keySet().iterator();

while(true) {
String ps;
while(true) {
if(!field.hasNext()) {
return sqlBuffer.toString();
}

ps = (String)field.next();
String[] ps1 = ps.split("&");
if(ps1.length == 1) {
if(ps.startsWith("@")) {
continue;
}

if(!first1) {
sqlBuffer = sqlBuffer.append(" and ");
}

first1 = false;
sqlBuffer = sqlBuffer.append(ps);
sqlBuffer = sqlBuffer.append(" = ");
break;
}

if(!first1) {
sqlBuffer = sqlBuffer.append(" and ");
}

first1 = false;
sqlBuffer = sqlBuffer.append(ps1[0]);
sqlBuffer = sqlBuffer.append(ps1[1]);
break;
}

sqlBuffer = sqlBuffer.append(conditions.get(ps));
}
} else {
sqlBuffer = sqlBuffer.append("select ");
if(conditions.containsKey("@query")) {
sqlBuffer = sqlBuffer.append(conditions.get("@query"));
} else {
sqlBuffer = sqlBuffer.append("id");
}

sqlBuffer = sqlBuffer.append(" from ");
if(conditions.containsKey("@table")) {
querySentence = (String)conditions.get("@table");
sqlBuffer = sqlBuffer.append(querySentence);
} else {
log.error("not get any table ");
}

sqlBuffer = sqlBuffer.append(" where 1 = 1 ");
querySentence1 = false;
Iterator first2 = conditions.keySet().iterator();

while(true) {
String field1;
while(true) {
if(!first2.hasNext()) {
if(conditions.containsKey("@group")) {
sqlBuffer = sqlBuffer.append(" group by ");
sqlBuffer = sqlBuffer.append(conditions.get("@group"));
}

if(conditions.containsKey("@order")) {
sqlBuffer = sqlBuffer.append(" order by ");
sqlBuffer = sqlBuffer.append(conditions.get("@order"));
}

sqlBuffer = sqlBuffer.append(" limit ");
sqlBuffer = sqlBuffer.append(start);
sqlBuffer = sqlBuffer.append(" , ");
sqlBuffer = sqlBuffer.append(limit);
return sqlBuffer.toString();
}

field1 = (String)first2.next();
String[] ps2 = field1.split("&");
if(ps2.length == 1) {
if(field1.startsWith("@")) {
continue;
}

sqlBuffer = sqlBuffer.append(" and ");
sqlBuffer = sqlBuffer.append(field1);
sqlBuffer = sqlBuffer.append(" = ");
break;
}

sqlBuffer = sqlBuffer.append(" and ");
sqlBuffer = sqlBuffer.append(ps2[0]);
sqlBuffer = sqlBuffer.append(ps2[1]);
break;
}

sqlBuffer = sqlBuffer.append(conditions.get(field1));
}
}
}

这里有一个坑爹的点是

/**
* 厂家任务列表拼接搜索条件sql
*
* @param id
* @param distributorShortName
* @param teamName
* @param minCreateAt
* @param maxCreateAt
* @param minPlanBeginAt
* @param maxPlanBeginAt
* @param status
* @param sortField
* @param sort
* @param count
* @return
*/
public static Map<String, Object> venderTaskList(Long id, String distributorShortName,
                                                String teamName, Long minCreateAt,
                                                Long maxCreateAt, Long minPlanBeginAt,
                                                Long maxPlanBeginAt, Integer status,
                                                String sortField, String sort, Long venderId,
boolean count) {
 Map<String, Object> map = new HashMap<>();
if (DataUtils.isNotNullOrEmpty(id)) {
   map.put("id", id);
 }
if (StringUtils.isNotEmpty(distributorShortName)) {
   map.put("distributor_short_name &like ", "'%" + distributorShortName + "%'");
 }
if (StringUtils.isNotEmpty(teamName)) {
   map.put("each_team_name &like ", "'%" + teamName + "%'");
 }
if (DataUtils.isNotNullOrEmpty(minCreateAt)) {
   map.put("create_at &>= ", minCreateAt);
 }
if (DataUtils.isNotNullOrEmpty(maxCreateAt)) {
   map.put("create_at &<= ", maxCreateAt);
 }
if (DataUtils.isNotNullOrEmpty(minPlanBeginAt)) {
   map.put("plan_begin_at &>= ", minPlanBeginAt);
 }
if (DataUtils.isNotNullOrEmpty(maxPlanBeginAt)) {
   map.put("plan_begin_at &<= ", maxPlanBeginAt);
 }
if (DataUtils.isNotNullOrEmpty(status)) {
   map.put("status", status);
 }
if (DataUtils.isNotNullOrEmpty(venderId)) {
   map.put("vender_id", venderId);
 }
if (count) {
   map.put("@query", "count(id)");
 }
 map.put("@table", "venderTask");

 map.put("@order", sortField + " " + sort);

//这里没有引入正确阐述,stat 和limit直接给定了参数为零.查看日志的时候会造成误导.

log.info("venderTaskList sql is: " + SQLUtil.convert2Sql(map, stat 0, limit 0));
return map;

}

到这里了底层的sql语句就基本清楚是怎么来的了,和mybatis不一样,都是动态组装,就是封装的有点狠,找了好几天才找全.

遇到的问题及其收获:

通过一层层的代码,理清了逻辑,和前面任务学的jdbc接在一起了.对DAL也有新的认识,虽然是小进步.但这种天天有新收获的感觉很错.加油.

明天的计划:

    大家都在坚持,我也要坚持!找点解决完海川的bug.


返回列表 返回列表
评论

    分享到