|
|
@@ -0,0 +1,214 @@
|
|
|
+[TOC]
|
|
|
+
|
|
|
+# 1. 为什么要翻新
|
|
|
+
|
|
|
+## 1.1. 代码可维护性
|
|
|
+
|
|
|
+mes的代码,采用的java拼装sql,然后sql非常复杂,大量无效流程分支的情况
|
|
|
+
|
|
|
+例如下面:一个看似简单的查询
|
|
|
+
|
|
|
+```java
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+```
|
|
|
+
|
|
|
+存在以下问题
|
|
|
+
|
|
|
+1. 参数全装list请求里。
|
|
|
+
|
|
|
+2. 部分sql由前端告知(存在严重的注入风险)
|
|
|
+
|
|
|
+3. 前端后端采用信任方式(不验证身份)
|
|
|
+
|
|
|
+4. 在xml里面另外又维护了大段sql,任何一个修改需要 从3个地方结合sql才能知道在干嘛
|
|
|
+
|
|
|
+5. \#号占位符,风险极高
|
|
|
+
|
|
|
+6. 很随意就星星分组查询
|
|
|
+
|
|
|
+例如下面:一个看似简单的查询对应的sql.xml部分
|
|
|
+
|
|
|
+```sql
|
|
|
+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
|
|
|
+```
|
|
|
+
|
|
|
+存在以下问题
|
|
|
+
|
|
|
+1. 字段随意转码 (正确做法是在java中转换,索引之敌)
|
|
|
+
|
|
|
+2. 随意的子查询 (在开发中是大忌)
|
|
|
+
|
|
|
+3. 随意的分组查询(分组查询不允许用在业务模块上)
|
|
|
+
|
|
|
+4. 多张表查询,应该尽量采用主表查询,从表拼装,多次查询的方式,这里为了省事一锅炖。
|
|
|
+
|
|
|
+5. 存在大量魔法占位符 \#column#,#something# 之类,难以理解 (带来了天量的维护困难)
|
|
|
+
|
|
|
+## 1.2. 并发及带来的相关灾难
|
|
|
+
|
|
|
+#### 1.2.1 概念
|
|
|
+
|
|
|
+ 事务
|
|
|
+
|
|
|
+ 一件事情,不管多少步骤,要么做完,要么不做,不允许出现中间状态
|
|
|
+
|
|
|
+> 例如:
|
|
|
+>
|
|
|
+> 小明给小方银行转账。步骤如下:
|
|
|
+> 1、小明,账上扣掉1块
|
|
|
+>
|
|
|
+> 2、小明流水上增加一条支出信息
|
|
|
+>
|
|
|
+> 3、小方,账上增加1块
|
|
|
+>
|
|
|
+> 4、小方流水上增加一条收入信息
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 如果不带事务,那么中间状态不能是每方都能接受的
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+所以,我们在实际工作中带上事务
|
|
|
+
|
|
|
+> 1、先冻结小明那条数据(其他人不能写或者读(不包括脏读))
|
|
|
+>
|
|
|
+> 2、小明zhangs
|
|
|
+>
|
|
|
+> 2、流水表写入2条可回退事务插入
|
|
|
+>
|
|
|
+> 3、冻结小方的那条数据(其他人不能读或者写)
|
|
|
+>
|
|
|
+>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 事务死锁
|
|
|
+
|
|
|
+1. 暴力解锁
|
|
|
+
|
|
|
+2. 并发
|
|
|
+
|
|
|
+3. 串行
|
|
|
+
|
|
|
+1. 并发及带来的相关灾难
|
|
|
+
|
|
|
+2. 项目健壮的重要性
|
|
|
+
|
|
|
+3. 翻新发现问题并带来可靠维护文档
|
|
|
+
|
|
|
+4. 可扩展开发性
|
|
|
+
|
|
|
+5. 翻新步骤
|
|
|
+
|
|
|
+6. 怎么保证翻新是可靠的,而不是带来新问题翻新步骤
|
|
|
+
|
|
|
+7. 施工进度怎么控制
|
|
|
+
|
|
|
+8. 旧系统下线的时机
|
|
|
+
|
|
|
+9. 甲方操作人员需要配合做什么
|
|
|
+
|
|
|
+10. 旧系统产生的历史错误数据如何处理
|
|
|
+
|
|
|
+11. 告警中台推销
|