2010-12-14 84 views
6

在我的數據庫接口庫jOOQ中,我想添加對Oracle(或DB2等)包的支持。我已經實現了存儲過程/函數支持,每個存儲對象都被建模爲生成的Java類。例如,該存儲功能Oracle包和Java包之間的映射

CREATE FUNCTION f_author_exists (author_name VARCHAR2) RETURNS NUMBER; 

將產生可以這樣使用一個類(注意,也有很多方便的方法,這個例子只是顯示了常規設計):

// A new "function call instance". The function needs to be instanciated 
// once per call 
FAuthorExists f = new FAuthorExists(); 

// Set the function parameters on the call instance and call it 
f.setAuthorName("Paulo"); 
f.execute(connection); 

// Fetch the result from the function call instance 
BigDecimal result = f.getReturnValue(); 

我選擇映射的原因SQL函數Java類是因爲存儲過程允許在調用過程後能夠一個接一個地讀取複雜的返回值(幾個OUT或IN OUT參數):

p.getOutParam1(); 
p.getOutParam2(); 

現在這種設計可以很好地與存儲的函數/程序一起工作,其中重載是不可能的。在甲骨文公司(或DB2的)封裝,但是,我可以有多個函數具有相同的名稱,如

CREATE PACKAGE my_package IS 
    FUNCTION f_author_exists (name VARCHAR2) RETURNS NUMBER; 
    FUNCTION f_author_exists (name VARCHAR2, country VARCHAR2) RETURNS NUMBER; 
END my_package; 

當我生成每個函數(或過程)的一類,我將有幾個FAuthorExists Java類命名衝突。蹩腳的解決方案是爲類名添加索引,如FAuthorExists2,FAuthorExists3。另一個蹩腳的解決方案是從參數名稱/類型直接生成某種類型的散列值(或值本身),例如FAuthorExistsVARCHAR2,FAuthorExistsVARCHAR2VARCHAR2。出於顯而易見的原因,這兩種解決方案都不可取

有沒有人有這個問題的簡單解決方案?或者也許是一個更好的總體設計的想法,不會產生這樣的函數名稱超載問題?

任何反饋讚賞!

回答

0

我發現沒有其他可行的方法來解決這個問題,而不是在生成的類上使用「過載索引」。因此,包

CREATE PACKAGE my_package IS 
    FUNCTION f_author_exists (name VARCHAR2) RETURNS NUMBER; 
    FUNCTION f_author_exists (name VARCHAR2, country VARCHAR2) RETURNS NUMBER; 
END my_package; 

會產生這些類:

public class FAuthorExists1 { /* ... */ } 
public class FAuthorExists2 { /* ... */ } 

其他的想法只會導致新的衝突,在代碼生成時,或在運行時。

UPDATE:請注意,這個解決方案也似乎是唯一一個來處理這樣一個正確的情況:

CREATE PACKAGE my_package IS 
    PROCEDURE f_author_exists (name VARCHAR2); 
    PROCEDURE f_author_exists (name CHAR); 
    PROCEDURE f_author_exists (name CHAR, country OUT VARCHAR2); 
END my_package; 

,因爲它似乎,這種超載有可能在PL/SQL,太。

3

getReturnValue功能能夠確定在調用時發生過載功能取決於有多少輸入參數已經被設置爲來電 - 但我認爲它最終會被更簡單,如果你堅持要像setParam1而不是setName

+0

'execute()'方法進行實際的調用。由於函數參數「name」,該方法被稱爲'setName()'。我在例子中解決了這個問題,使其更加清晰。你的想法不錯。儘管如此,問題在於如果函數名稱重載的參數集非常不同,那麼可能會發現混淆,可能會有哪些參數組合。但是,通過便利的方法,這可能確實有效! +1爲在運行時確定正確調用的想法 – 2010-12-14 15:40:20

+0

@Lukas匹配參數類型而不是名稱是我的建議 - 我認爲它可能更簡單。不過,我認爲原則上兩者都有可能。 – 2010-12-14 15:48:32

+0

很容易找到一個關於如何根據參數名稱/類型/位置調用函數的好實現。但困難的部分是讓生成的代碼易於開發人員使用。這就是爲什麼我在生成的方法中使用參數的名稱 – 2010-12-14 16:36:02

0

您可以通過爲每個函數提供唯一名稱來克服重載的侷限性。這也會提高代碼的可讀性(這是why Golang doesn't have overloading的原因之一)。例如f_author_name_exists,f_author_name_country_exists。

使Java類複雜化的另一種方法是在運行時根據使用哪個重載Java構造函數或使用哪個setter來決定調用哪個過程。

+0

感謝您的提示。正如問題所述,這是關於[jOOQ](http://www.jooq.org),一種爲存儲過程生成源代碼的實用程序,所以我無法控制過程名稱重載 - 我不'根本不介意。它在創建便捷方法時增加了API的表現力。另一方面,由於'OUT'參數的存在,很難決定在運行時調用哪個過程,如果該調用在代碼生成時沒有硬連線... – 2012-05-11 07:13:55