【正文】
實現(xiàn)的。 所以根據(jù)方案 1的失敗,要想很好的 做到代碼重用,就很有必要引入面向?qū)ο蟮乃枷?,采用繼承的方法,做到條件組合,就好像類與類之間的繼承。作為表中列名出現(xiàn)的字段,是不可能相互組合的。但是換個角度,大膽的設(shè)想,如果把這些字段不作為列名,能不能做到相互組合呢?如果把這些字段轉(zhuǎn)換成變量,對變量一一賦值,和作為字段相比并沒有做到很大的改善。 如果把這些字段轉(zhuǎn)換成表中的記錄值呢?試想一下,似乎看到一線光明,因為在 PL/SQL 里,可以用到動態(tài) SQL 的方法,這樣可以所需要的條件動態(tài)的組合了。 但是能不能真正達(dá)到便于動態(tài)控制,便于動態(tài)修改,以及便于維護(hù)呢?我們需 要一步一步去研究,以及測試。 根據(jù) 目前得出的結(jié)論,我們現(xiàn)在需要一個表,表中的某一列的記錄值為Complexity 表中作為篩選條件的列名,如下 表 2所示: 表 2 FIELD 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 主鍵 NAME 文本 COLUMN_NAME 文本 列名 FIELD 表中的 COLUMN_NAME 列存放 Complexity 表中作為篩選條件的列名。 這樣 就可以做到把條件一步一步‘拼起來’了。 接著往下分析。需要 選取出可能作為篩選條件的列名 C_U C_U C_UC_U4 四個字段,以后的分析 將會以它們作為例子。 這里 把每個單獨的列名作為篩選條件的條件叫做簡單條件,而多個簡單條件組合而成的條件叫做復(fù)雜條件。值得注意的是 ,篩選條件中有相當(dāng)一部分是類似于‘ C_U1 IN (A, B, C, D)’的,它也是簡單條件,但是比較特殊一點, 這樣的條件 把它叫做簡單序列條件。 假設(shè)現(xiàn)在客戶 Ted需要的數(shù)據(jù)是以 C_U1A和 C_U2B或者 C_U3=C 和 C_U1=D作為篩選條件而獲取的,而另一客戶 Robin 需要的數(shù)據(jù)則是以 C_U1A 和 C_U2B并且 C_U3=C 和 C_U1=D 作為篩選條件而獲取的。 現(xiàn)在 可以 得到一個結(jié)論:兩個簡單條件間的關(guān)系只有兩種, AND 和 OR。也就是說不論一個復(fù)雜條件是由多少個簡單條件組合而成,這些簡單條件間的關(guān)系只有兩種。這是一個有趣的結(jié)論。 現(xiàn)在就可以做到把一個個簡單條件通過兩種關(guān)系的一種‘拼裝’起來,組合而成一個個復(fù)雜條件。而對于多個組成部分有著重復(fù)簡單條件的復(fù)雜條件,它們可以說是相互繼承的,這樣就從功能邏輯上做到了繼承與組合。 復(fù) 雜 條 件 簡 單 條 件 簡 單 序 列 條 件A N D / O R 圖 2 條件間邏輯關(guān)系圖 通過上圖,很容易想到,這里 只需要在數(shù)據(jù)庫中創(chuàng)建五個表來來實現(xiàn)這 一方式,也 就是 可以做到需求里的篩選條件間的自由組合這一功能了。 通過建立外鍵, 可以很容易的做到把 FIELD 里的 COLUMN_NAME 字段一一映射到簡單條件表和序列條件表中,而這兩個表通過聯(lián)接表可以組合成復(fù)雜條件存放到復(fù)雜條件表中。 C O N D I T I O NP K I D N A M E N E G A T E D C O N T A I N E R _ I DC O M P O U N D _ C O N D I T I O NP K I D C O N J U N C T I O N _ I DS I M P L E _ C O N D I T I O NP K I D N A M E V A L U E O P E R A T O R _ I D F I E L D _ I DL I S T _ C O N D I T I O NP K I D F I E L D _ I DC O N J U N C T I O NP K I D N A M E C O D EF I E L D P K I D N A M E C O L U M N _ N A M E 圖 3 條件功能組合圖一 到此 就可以實現(xiàn)需求里的篩選條件間的自由組合這一功能了。 還 需 要想辦法去實現(xiàn)篩選條件需要去匹配的值是具有特定意義的,而且客戶可以定制這一需求。 試想一下, 如果現(xiàn)在不對這些值不做任何處理,那 可以想 象開發(fā)人員 將會 固定的把這些有著特定意義的數(shù)值寫在 PL/SQL 程序中,這樣做是不能做到客戶靈活定制的,而且顯而易見的是,從安全的角度出發(fā),這樣做也是不安全的。 為了能靈活控制,能按照客戶的需求進(jìn)行規(guī)范的定制,這些數(shù)值也必須是‘拼裝’起來的。所以必須要把這些數(shù)值存放到表中去。 對于簡單條件, 只需要把需要匹配的數(shù)值存放在簡單條件表的 VALUE 字段中就可以了。 對于序列條件,則不能這樣,因為它需要去匹配的是,是否存在于某一范圍的數(shù)值當(dāng)中,例如判斷‘ C_U1 IN (A,B,C,D)’是否成立。而這些數(shù)值( A 或者 B或者 C等)是具有 特定意義的。 所以為了能把這些數(shù)值‘拼裝’起來,這些數(shù)值就需要獨立的存放在一張表中。 那就 需要再創(chuàng)建一張表 LIST_CONDITION_MATCH_VALUE。 現(xiàn)在需要創(chuàng)建的表的框架如下: C O N D I T I O NP K I D N A M E N E G A T E D C O N T A I N E R _ I DC O M P O U N D _ C O N D I T I O NP K I D C O N J U N C T I O N _ I DS I M P L E _ C O N D I T I O NP K I D N A M E V A L U E O P E R A T O R _ I D F I E L D _ I DL I S T _ C O N D I T I O NP K I D F I E L D _ I DC O N J U N C T I O NP K I D N A M E C O D EF I E L D P K I D N A M E C O L U M N _ N A M EL I S T _ C O N D I T I O N _ M A T C H _ V A L U E 1P K I D L I S T _ C O N D I T I O N _ I D M A T C H _ V A L U E 圖 4 條件功能組合圖二 到此,對于復(fù)雜表中作為篩選條件的字段比較多(大約 250 個),且相互組合,而篩選條件需要去匹配的值是具有特定意義的,且可以根據(jù)客戶的需要進(jìn)行定制這一基本需求,我們也基本做到了動態(tài)控制,動態(tài)修改,并且便于維護(hù)。 現(xiàn)在 要產(chǎn)生一個復(fù)雜的篩選條件, 就可以通過寫 PL/SQL 程序來從相關(guān)表中讀取出來需要的值,再‘拼裝’起來就可以了。 但是有一個問題,假設(shè)通過 寫程序來產(chǎn)生了非常多的篩選條件,某一天,客戶需要再增加一系列 數(shù)量眾多的篩選條件,會發(fā)生什么呢?那就 會花大量的時間去寫代碼。盡管目前的設(shè)計 已經(jīng) 做到了條件的動態(tài)組合化,匹配的數(shù)值也可以做到動態(tài)組合化,但是開發(fā)人員需要寫的代碼有絕大數(shù)將是架構(gòu)類似的。換句話說,這樣的設(shè)計會花了大量的時間 在做類似的事情上。 很明顯, 做到的靈活控制,還不夠靈活。問題在哪兒呢?分析一下,對于簡單條件,比如‘ C_U1 A’ 或者‘ C_U2=B’,篩選列和匹配的數(shù)值我們都可以在相關(guān)表中取到,而篩選列和匹配的數(shù)值之間的關(guān)系,例如大于,小于,等于,時間從某時間開始,這些關(guān)系是我們在寫代碼的時候一直在重復(fù)的寫的。而正是因為這個原因,代碼不能做到代碼間的繼承和重用,這是一個失敗指出。 要是通過接口設(shè)計 能把這些關(guān)系像處理篩選列與匹配的數(shù)值一樣處理,這個問題也就解決了。能做到么?答案是肯定的。因為這些關(guān)系也就只有數(shù)種,例如數(shù)字間的比較,時間數(shù)值之間的比較,諸如此類的關(guān)系是可以得到有效控制的。 對于序列條件,只有兩種關(guān)系,即是否‘ IN’,很顯然也可 以得到有效的控制。 通過以上的分析,現(xiàn)在 只需要再加一個表就可以了,這張表用來存放簡單條件的篩選列與匹配的數(shù)值之間的關(guān)系種類,而對于序列條件,就不用,在程序里很容易做到動態(tài)處理。為了不占據(jù)篇幅,數(shù)據(jù)篩選接口的完整數(shù)據(jù)庫架構(gòu)會在后面的數(shù)據(jù)建模部分中一并出現(xiàn)。 5 數(shù)據(jù)建模 數(shù)據(jù)模型的建立 根據(jù)解決方案的設(shè)計,畫出數(shù)據(jù)篩選接口的完整數(shù)據(jù)庫架構(gòu), 如后頁 圖所示: C O N D I T I O NP K I D N A M E N E G A T E D C O N T A I N E R _ I DC O M P O U N D _ C O N D I T I O NP K I D C O N J U N C T I O N _ I DS I M P L E _ C O N D I T I O NP K I D N A M E V A L U E O P E R A T O R _ I D F I E L D _ I DL I S T _ C O N D I T I O NP K I D F I E L D _ I DC O N J U N C T I O NP K I D N A M E C O D EC O N D I T I O N _ O P E R A T O RP K I D C O D E N A M EF I E L D P K I D N A M E C O L U M N _ N A M EL I S T _ C O N D I T I O N _ M A T C H _ V A L U EP K I D L I S T _ C O N D I T I O N _ I D M A T C H _ V A L U E圖 5 數(shù)據(jù)庫架構(gòu) 圖 數(shù)據(jù)庫表結(jié)構(gòu)的設(shè)計 根據(jù)前面完成的解決方案的設(shè)計以 及數(shù)據(jù)模型的 建立, 可以設(shè)計出完整的數(shù)據(jù)庫表結(jié)構(gòu)。具體設(shè)計如下: 用于存放篩選條件,具體設(shè)計如表 3 所示: 表 3條件表 CONDITION 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 NAME 文本 條件名字 NEGATED 數(shù)字 判斷是否為否定字段 CONTAINER_ID 數(shù)字 判斷是否屬于復(fù)合條件字段 用于存放條件聯(lián)接符,具體設(shè)計如表 4所示: 表 4條件聯(lián)接符表 CONJUNCTION 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 NAME 文本 名字 CODE 文本 聯(lián)接符編碼 用于存 放復(fù)合條件,具體設(shè)計如表 5 所示: 表 5復(fù)合條件表 COMPOUND_CONDITION 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 CONJUNCTION_ID 數(shù)字 聯(lián)接符編號 用于存放簡單條件信息,具體設(shè)計如表 6 所示: 表 6簡單條件表 SIMPLE_CONDITION 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 NAME 文本 簡單條件名字 VALUE 文本 簡單條件數(shù)值 OPERATOR_ID 數(shù)字 條件運算符編號 FIELD_ID 數(shù)字 篩選列編號 用于存放條件運算符信 息,具體設(shè)計如表 7所示: 表 7條件運算符表 CONDITION_OPERATOR 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 NAME 文本 條件運算符名字 CODE 文本 條件運算符編碼 用于存放序列條件信息,具體設(shè)計如表 8 所示: 表 8序列條件表 LIST_CONDITION 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 FIELD_ID 數(shù)字 篩選列編號 用于存放序列條件需要去匹配的數(shù)值信息,具體設(shè)計如表 9 所示: 表 9序列條件匹配數(shù)值表 LIST_CONDITION_MATCH_VALUE 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 LIST_CONDITION_ID 數(shù)字 序列條件編號 MATCH_VALUE 文本 序列條件匹配值 用于存放篩選列信息,具體設(shè)計如表 10所示: 表 10篩選列信息表 FIELD 字段名 數(shù)據(jù)類型 說明 ID 數(shù)字 編號字段 主鍵 NAME 文本 篩選列名字 (可作標(biāo)記 ) COLUMN_NAME 文本 實際篩選列名 數(shù)據(jù)庫基礎(chǔ)視圖的設(shè)計 通過之前的分析,我發(fā)現(xiàn)數(shù)據(jù)庫中的八個表之間關(guān)聯(lián)比較多, 應(yīng)該把通常發(fā)生關(guān)聯(lián)的表封裝起來,視圖正 是實現(xiàn)這個‘封裝’的最佳選擇。 需要創(chuàng)建四個視圖,分別為簡單條件視圖,序列條件視圖,組合條件視圖,以及條件視圖。通過這四個視圖可以把簡單條件,序列條件,以及組合條件和FIELD 表很好的封裝起來。為了避免占據(jù)過多篇幅,這里只以序列條件視圖和組合條件視圖為例。 序列條件視圖: CREATE OR REPLACE VIEW V_LIST_CONDITION (FIELD_NAME, COLUMN_NAME, FIELD_TYPE_NAME, FIELD_TYPE_CODE, FIELD_TABLE_TYPE_NAME, FIELD_TABLE_TYPE_CODE, NEGATED, ITEM_COUNT, ID, FIELD_ID, FIELD_TY