[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. 串行

4. 并发及带来的相关灾难

5. 项目健壮的重要性

6. 翻新发现问题并带来可靠维护文档

7. 可扩展开发性

8. 翻新步骤

9. 怎么保证翻新是可靠的，而不是带来新问题翻新步骤

10. 施工进度怎么控制

11. 旧系统下线的时机

12. 甲方操作人员需要配合做什么

13. 旧系统产生的历史错误数据如何处理

14. 告警中台推销
