[TOC]
mes的代码,采用的java拼装sql,然后sql非常复杂,大量无效流程分支的情况
例如下面:一个看似简单的查询
public CoreReturnObject doQueryData(ArrayList<String> list,String[] arr,String strPlanSql,String bathYear)
{
String sql = CoreXmlSqlParsersFactory.getSql("FrmReportOutput.doQueryData").replace("#COLUMNS#", list.get(0));
sql +=CoreConverter.toSqlConditionString("t.STORAGE_NO", arr);
sql = sql.replace("#CONDITIONS#", list.get(1));
sql = sql + list.get(2);
sql += " )F1)F";
sql += " LEFT JOIN (SELECT SUM(NVL(T1.CUT_WEIGHT,'0')*NVL(T1.REAL_INDOUBLE_NUM,'0')) CUT_WEIGHT,#JUDGE_STOVE_NO1# T1.HEAT_PLAN_NO,T1.PRO_PLAN_ID,T1.GX_PLAN_NO FROM PLN_ZY_ZG_C T1,MIL_PLAN S1 WHERE T1.HEAT_PLAN_NO = S1.ID AND S1.BACK_PLAN_FLAG = '0'" +
" AND S1.BACK_SLAB_FLAG = '0' AND T1.CUT_TARGET = '返废' #BATH_YEAR# GROUP BY #JUDGE_STOVE_NO1# T1.HEAT_PLAN_NO,T1.PRO_PLAN_ID,T1.GX_PLAN_NO) D ON F.PRO_PLAN_ID_ZG = D.PRO_PLAN_ID AND F.GX_PLAN_NO_ZG = D.GX_PLAN_NO #DD# ";
sql += " AND F.OUTSTOCK_TYPE_CODE = '800801' AND F.RK =1";
if(!strPlanSql.equals(""))
{
sql = sql.replace("#DD#", strPlanSql).replace("#JUDGE_STOVE_NO#", "JUDGE_STOVE_NO,").replace("#JUDGE_STOVE_NO1#", "T1.JUDGE_STOVE_NO,");
}else
{
sql = sql.replace("#DD#", "").replace("#JUDGE_STOVE_NO#", "").replace("#JUDGE_STOVE_NO1#", "");
}
if(!bathYear.equals(""))
{
sql = sql.replace("#BATH_YEAR#", " AND S1.BAL_YEAR_MONTH = '"+bathYear+"'");
}else
{
sql = sql.replace("#BATH_YEAR#", "");
}
return this.getData(sql);
}
存在以下问题
参数全装list请求里。
部分sql由前端告知(存在严重的注入风险)
前端后端采用信任方式(不验证身份)
在xml里面另外又维护了大段sql,任何一个修改需要 从3个地方结合sql才能知道在干嘛
#号占位符,风险极高
很随意就星星分组查询
例如下面:一个看似简单的查询对应的sql.xml部分
select
#columns#,
DECODE(T1.IS_DEALER, '0', '自用', '1', '双经销', '2', '来料加工','3','定销订购') IS_DEALER,
DECODE(T1.BACK_FLAG, '0', '正常坯', '1', '回炉坯','2','套尺坯') BACK_FLAG,
MAX(S1.PLAN_TIME_B) PLAN_TIME_B,
T2.LOCATION_NAME,
T2.LARY_NO,
T2.STORAGE_NO,
(SELECT T3.STORAGE_NAME
FROM YDM_BS_STORAGE T3
WHERE T3.STORAGE_NO = T2.STORAGE_NO) STORAGE_NAME,
T1.PRODUCT_FLAG,
T1.MAT_STATUS,
T1.STOVE_NO,
T1.JUDGE_STOVE_NO,
T1.JUDGE_STOVE_NO_LG,
T1.SOURE_NAME,
T1.MATERIAL_NAME,
T1.GRADENAME,
S1.ORDER_NO || '/' || S1.ORDER_SEQ AS ORDER_NO,
T1.DIMATER,
T1.ACT_LEN,
T1.FIX_NUM,
T1.FIX_LEN,
DECODE(T1.QCM_STAUS, '00', '合格', '11', '待处理', '22', '废品') QCM_STAUS,
T1.PLINE_NAME,
T1.BELONG_NAME,
MAX(TO_CHAR(T1.INSTOCK_TIME, 'YYYY-MM-DD HH24:MI:SS')) INSTOCK_TIME,
T1.MEMO,
T1.MEMO MEMO2,
(SELECT T2.BASENAME
FROM COM_BASE_INFO T2
WHERE T2.BASECODE = T1.JUDGE_RESULT_CODE) JUDGE_RESULT_CODE,
MAX((SELECT S1.PLINE_NAME
FROM PLN_ORDER_ZG_S S1
WHERE S1.PRO_PLAN_ID = T1.PRO_PLAN_ID_ZG
AND S1.GX_PLAN_NO = T1.GX_PLAN_NO_ZG)) PLINE_NAME_NEXT,
sum(T1.ACT_COUNT) as ACT_COUNT,
sum(T1.ACT_WEIGHT) as ACT_WEIGHT,
T1.MNG_LOCK_FLAG
FROM MAT_GP_M T1
LEFT JOIN YDM_GP_BUTTRESS T2
on T1.MAT_NO = T2.MAT_NO
LEFT JOIN YDM_BS_STORAGE S
ON S.STORAGE_NO = T2.STORAGE_NO
LEFT JOIN PLN_ORDER_ZG_S S1
ON T1.PRO_PLAN_ID_ZG = S1.PRO_PLAN_ID
AND T1.GX_PLAN_NO_ZG = S1.GX_PLAN_NO
WHERE T1.MAT_NO = T2.MAT_NO
AND T1.IS_SETFOOT = '0'
#something#
group by T1.IS_DEALER,
T1.BACK_FLAG,
T2.LOCATION_NAME,
T2.LARY_NO,
T2.STORAGE_NO,
T1.PRODUCT_FLAG,
T1.MAT_STATUS,
T1.STOVE_NO,
T1.JUDGE_STOVE_NO,
T1.JUDGE_STOVE_NO_LG,
T1.SOURE_NAME,
T1.MATERIAL_NAME,
T1.GRADENAME,
S1.ORDER_NO,
S1.ORDER_SEQ,
T1.DIMATER,
T1.ACT_LEN,
T1.FIX_NUM,
T1.FIX_LEN,
T1.QCM_STAUS,
T1.PLINE_NAME,
T1.BELONG_NAME,
T1.MEMO,
T1.JUDGE_RESULT_CODE,
T1.MNG_LOCK_FLAG
存在以下问题
字段随意转码 (正确做法是在java中转换,索引之敌)
随意的子查询 (在开发中是大忌)
随意的分组查询(分组查询不允许用在业务模块上)
多张表查询,应该尽量采用主表查询,从表拼装,多次查询的方式,这里为了省事一锅炖。
存在大量魔法占位符 #column#,#something# 之类,难以理解 (带来了天量的维护困难)
事务
一件事情,不管多少步骤,要么做完,要么不做,不允许出现中间状态
例如:
小明给小方银行转账。步骤如下: 1、小明,账上扣掉1块
2、小明流水上增加一条支出信息
3、小方,账上增加1块
4、小方流水上增加一条收入信息
如果不带事务,那么中间状态不能是每方都能接受的
所以,我们在实际工作中带上事务
1、先冻结小明那条数据(其他人不能写或者读(不包括脏读))
2、小明zhangs
2、流水表写入2条可回退事务插入
3、冻结小方的那条数据(其他人不能读或者写)
事务死锁
暴力解锁
并发
串行
并发及带来的相关灾难
项目健壮的重要性
翻新发现问题并带来可靠维护文档
可扩展开发性
翻新步骤
怎么保证翻新是可靠的,而不是带来新问题翻新步骤
施工进度怎么控制
旧系统下线的时机
甲方操作人员需要配合做什么
旧系统产生的历史错误数据如何处理
告警中台推销