2012-06-21 36 views
2

我想調用存儲過程(Oracle)。由於我的程序調用是動態的,我需要動態地管理程序參數。 問題是我想避免使用instanceof關鍵字,因爲它不適合主要類型。 有沒有更簡單的方法來調用這樣的程序?Java - 使用泛型參數調用存儲過程

public void executeProcedure(StoredProcedure proc) {   
     LinkedList<ProcedureParameter<?>> parameters = proc.getParameters(); 

     CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE(?, ?, ?) }"); 

     for (int i = 0; i < parameters.size(); i++) { 
      Object paramValue = parameters.get(i).getValue(); 

      // Beginning of smelly code 

      if (paramValue instanceof String) { 
       statement.setString(i + 1, (String) paramValue); 
      } 
      else if (paramValue instanceof ...) { 
       ... 
      } 
      else { 
       ... 
      } 

      // End of smelly code 
     } 

     statement.execute();    
    } 

public class ProcedureParameter<E> { 
     private String name; 
     private E value; 

     public ProcedureParameter(String name) { 
      this.name = name; 
     } 

     public ProcedureParameter(String name, E value) { 
      this.name = name; 
      this.value = value; 
     } 

     // Getters and setters 
    } 

謝謝你的任何想法。

+0

如果你唯一的問題是基本類型,我建議你只是使用它們的對象包裝等價物,並讓你的生活變得容易 – ControlAltDel

+2

@ControlAltDel我認爲問題更多的是當向Statement添加參數時,你必須指定類型 - 即'statement.setString,statement.setInteger'等。 – chama

+0

@ControlAltDel這是一個好主意,但問題範圍更廣泛;我的意思是,可能的參數類型的數量是相當大的,我正在尋找一種解決方案,以避免長的if-else序列。 – dounyy

回答

1

我會實施另一種解決方案,可能不是最好的解決方案,但在我看來,雖然沒有臭味。

由於StoredProcedure是一個接口,每個存儲過程都實現了這個數據庫。因此,每個實現都將包含一個返回call ...語句的方法,因爲開發人員知道他實現的過程所需的參數類型。

+0

你想介紹一下這個答案嗎?我對使用StoredProcedures並試圖將我的頭圍繞在這個方面很陌生。更多的搜索,我發現這個實現,是類似的東西? http://www.codeguru.com/csharp/csharp/cs_misc/sampleprograms/article.php/c8981/Generic-Code-to-Execute-Stored-Procedures.htm謝謝! – user1580431

1

我認爲它可以幫助你不用instanceof來實現所需的功能:http://en.wikipedia.org/wiki/Visitor_pattern

+0

謝謝,但它不會幫助我,因爲我不使用自定義類型,但主要類型或「java」類型(如字符串) – dounyy

1

您可以使用反射,但因爲它的速度較慢,這不是很好的做法,防止編譯器檢查,以確保該方法調用正確。您可以將每個類映射到其相應的CallableStatement方法。例如String將被映射到「setString」。

List<ProcedureParameter<?>> parameters = proc.getParameters(); 
CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE(?, ?, ?) }"); 

Map<Class<?>, String> methods = new HashMap<Class<?>, String>(); 
methods.put(String.class, "setString"); 
//... 

for (int i = 0; i < parameters.size(); i++) { 
    Object paramValue = parameters.get(i).getValue(); 
    Class<?> paramValueClass = paramValue.getClass(); 
    String stmtMethod = methods.get(paramValueClass); 
    if (stmtMethod != null){ 
    Method method = statement.getClass().getMethod(stmtMethod, int.class, paramValueClass); 
    method.invoke(statement, i+1, paramValue); 
    } else { 
    //error 
    } 
} 
+0

那麼,該解決方案似乎比「if-else」解決方案更重。 ..謝謝無論如何:) – dounyy

+1

@dounyy是的我同意我只是提出這個答案,因爲我很無聊。 :) if/else解決方案也非常易讀 - 如果我對代碼庫很陌生,我可以很容易地看到發生了什麼。如果這些都是重構的,並且隱藏在其他一些類的後面,那麼它就很難弄清楚一切正在發生什麼。 – Michael

相關問題