2014-09-02 97 views
1

我正在學習如何使用SQLData並將問題轉換回我的對象​​。Java SQLData - 使用列表/數組投影到用戶對象?

我的Oracle類型看起來是這樣的:

CREATE OR REPLACE TYPE activities_t AS OBJECT 
(
    list activity_list_t; 
); 

CREATE OR REPLACE TYPE activity_list_t AS TABLE OF activity_t; 

CREATE OR REPLACE TYPE activity_t AS OBJECT 
(
    startDate DATE; 
    endDate DATE; 
); 

而且我的Java是這樣的:

public class Activities implements SQLData { 
    private String sqlType = "ACTIVITIES_T"; 
    List<Activity> list; 

    // must have default ctor! 
    public Activities() { 
    } 

    public String getSQLTypeName() throws SQLException 
    { 
     return sqlType; 
    } 

    public List getList() { 
     return list; 
    } 

    public void setList(List list) { 
     this.list = list; 
    } 

    public void readSQL(SQLInput stream, String typeName) throws SQLException 
    { 
     Array a = stream.readArray(); 
     // :(
    } 

    public void writeSQL(SQLOutput stream) throws SQLException 
    { 
     // stream.writeArray(this.list); 
    } 
} 

我試過在readSQL了一些東西,但我沒有太多的成功 - 我錯過了什麼?

我打電話其中有 「activities_t」 的OUT參數PLSQL存儲過程使用JDBC:

Map map = connection.getTypeMap(); 
map.put("ACTIVITIES_T", Class.forName("Activities")); 
connection.setTypeMap(map); 

callableStatement = connection.prepareCall("{call GET_ACTIVITIES(?)}"); 
callableStatement.execute(); 

謝謝! 史蒂夫

(最上面是從內存中的代碼是在工作中......)

回答

2

你需要添加一個類型映射ACTIVITY_T類型,以及一個爲ACTIVITIES_T。你的問題並不清楚你是否已經這樣做了。

我們假設你已經完成了這個操作並創建了一個名爲Activity的類,它也實現了SQLData。一旦你這樣做了,下面應該足以內Activities讀取活動列表:

public void readSQL(SQLInput stream, String typeName) throws SQLException { 
     Array array = stream.readArray(); 
     this.list = new ArrayList<Activity>(); 
     for (Object obj : (Object[])array.getArray()) { 
      list.add((Activity)obj); 
     } 
    } 
+0

謝謝,一旦我解決了問題,我錯過了其他類型映射我最終得到了類似的東西:) – Steve 2014-09-04 03:20:28

+0

感謝您的答案,但writeSQL實現呢?我無法找到將List轉換爲java.sql.Array的正確方法。 – 2016-10-17 10:29:42

+0

@DmitryAvgustis:怎麼樣[這個問題](http://stackoverflow.com/questions/11439543)? – 2016-10-18 21:16:27

0

提示:

  • JDBC API是大小寫敏感的關於類型名稱;如果您的類型名稱不完全匹配,您將看到Unable to resolve type錯誤。除非您在create語句中雙引號,否則Oracle將大寫您的類型名稱。
  • 如果類型不在默認模式中,您可能需要指定SCHEMA.TYPE_NAME
  • 如果您要連接的用戶不是所有者,請記住grant execute的類型。
    如果您對包執行了操作,但沒有執行類型,則getArray()將在嘗試查找類型元數據時引發異常。

的getArray()

我的解決方案基本相同,盧克的。但是,我需要在獲取數組時提供類型映射:array.getArray(typeMap) 您也可以在Connection上設置默認類型映射,但這對我無效。

當調用getArray()時,您將獲得一個對象類型的數組,即在SQLData實現您所創建的代表activity_t

這裏是你可能會發現有用泛型函數:

public static <T> List<T> listFromArray(Array array, Class<T> typeClass) throws SQLException { 
    if (array == null) { 
     return Collections.emptyList(); 
    } 
    // Java does not allow casting Object[] to T[] 
    final Object[] objectArray = (Object[]) array.getArray(getTypeMap()); 
    List<T> list = new ArrayList<>(objectArray.length); 
    for (Object o : objectArray) { 
     list.add(typeClass.cast(o)); 
    } 
    return list; 
} 

writeArray()

搞清楚如何寫一個數組是令人沮喪的,甲骨文的API需要連接才能創建陣列,但在writeSQL(SQLOutput sqlOutput)的上下文中沒有明顯的連接。幸運的是,this blog有一個技巧/破解得到OracleConnection,我在這裏使用。

當你創建一個數組createOracleArray()指定類型名稱,而不是對象類型列表類型。即activity_list_t

下面是寫入數組的一個通用函數。在你的情況,listType"activity_list_t",你會傳遞一個List<Activity>

public static <T> void writeArrayFromList(SQLOutput sqlOutput, String listType, @Nullable List<T> list) throws SQLException { 
    final OracleSQLOutput out = (OracleSQLOutput) sqlOutput; 
    OracleConnection conn = (OracleConnection) out.getSTRUCT().getJavaSqlConnection(); 
    conn.setTypeMap(getTypeMap()); // not needed? 
    if (list == null) { 
     list = Collections.emptyList(); 
    } 
    final Array array = conn.createOracleArray(listType, list.toArray()); 
    out.writeArray(array); 
} 

注:在一個點上我認爲setTypeMap是必需的,但現在當我刪除了這一行我的代碼仍然有效,所以我不肯定是否有必要。

+0

Oracle區分大小寫,並不區分大小寫 - 默認行爲是將所有未加引號的標識符轉換爲大寫(因此它似乎不區分大小寫),但您可以使用雙引號將標識符禁止該行爲,並且它會尊重標識符的大小寫敏感性。 – MT0 2017-08-29 08:22:57

+0

編輯澄清。如果我小寫一個類型名稱,我得到這個錯誤 '''錯誤代碼[17060];無法構造描述符:無法解析類型「MYSCHEMA.mytype」;嵌套異常是java.sql.SQLException:無法構造描述符:無法解析類型「MYSCHEMA.mytype''' – Arlo 2017-08-30 21:02:38

+0

如果在Oracle中執行CREATE TYPE MYSCHEMA。mytype」IS ...',那麼您將得到一個類型其中類型的標識符是區分大小寫的(小寫)如果你做'CREATE TYPE MYSCHEMA.mytype IS ...'(不帶引號),那麼你將得到一個類型的標識符是'MYTYPE'的類型(在上因爲Oracle會在後臺將未加引號的標識符轉換爲大寫。您的開頭一行「即使Oracle不區分大小寫」也是不正確的 - 當您使用帶引號的標識符且不使用帶引號的標識符時,Oracle區分大小寫標識符會將所有內容都轉換爲大寫。 – MT0 2017-08-31 08:40:50