2010-03-24 49 views
1

爲了安全和性能的原因,我正在修改一些使用preparedStatement而不是普通Statement的代碼。Java中針對Oracle的PreparedStatement問題

我們的應用程序目前正在將信息存儲到嵌入式德比數據庫中,但我們即將轉向Oracle。

我發現兩件事情,我需要對Oracle和預處理語句您的幫助傢伙:

1 - 我發現this document說,甲骨文沒有處理綁定參數爲IN子句,所以我們不能提供查詢如下:

Select pokemon from pokemonTable where capacity in (?,?,?,?) 

這是真的嗎?有什麼解決方法嗎? ...爲什麼?

2-我們有一些類型爲TIMESTAMP的字段。因此,根據我們的實際聲明,查詢如下所示:

Select raichu from pokemonTable where evolution = TO_TIMESTAMP('2500-12-31 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF') 

準備好的聲明應該做什麼?我應該加入參數數組: 2500-12-31或TO_TIMESTAMP('2500-12-31 00:00:00.000','YYYY-MM-DD HH24:MI:SS.FF')?

感謝您的幫助,我希望我的問題很明確!

Regards,

回答

1

我有點驚訝地看到這個文件。這是事實,就像跟着你不能設置一個數組/集合(這是無論使用的數據庫/ JDBC驅動程序):

String sql = "SELECT col FROM tbl WHERE id IN (?)"; 
statement = connection.prepareStatement(sql); 
statement.setArray(1, arrayOfValues); // Fail. 

但是,文件中提到的查詢應該工作。至少在Oracle 10g XE和ojdbc14.jar的組合中,我可以從經驗中得知這一點。我懷疑這個文檔的作者是不是混淆了事情,或者它實際上涉及DB和/或JDBC驅動程序的不同(更舊的版本)版本。

無論使用什麼JDBC驅動程序(雖然您依賴數據庫使用了IN子句可以包含多少項目,Oracle(有,再次)具有大約1000個項目的限制),下列內容應該可以工作:

private static final String SQL_FIND = "SELECT id, name, value FROM data WHERE id IN (%s)"; 

public List<Data> find(Set<Long> ids) throws SQLException { 
    Connection connection = null; 
    PreparedStatement statement = null; 
    ResultSet resultSet = null; 
    List<Data> list = new ArrayList<Data>(); 
    String sql = String.format(SQL_FIND, preparePlaceHolders(ids.size())); 

    try{ 
     connection = database.getConnection(); 
     statement = connection.prepareStatement(sql); 
     setValues(statement, ids.toArray()); 
     resultSet = statement.executeQuery(); 
     while (resultSet.next()) { 
      Data data = new Data(); 
      data.setId(resultSet.getLong("id")); 
      data.setName(resultSet.getString("name")); 
      data.setValue(resultSet.getInt("value")); 
      list.add(data); 
     } 
    } finally { 
     close(connection, statement, resultSet); 
    } 

    return list; 
} 

public static String preparePlaceHolders(int length) { 
    StringBuilder builder = new StringBuilder(); 
    for (int i = 0; i < length;) { 
     builder.append("?"); 
     if (++i < length) { 
      builder.append(","); 
     } 
    } 
    return builder.toString(); 
} 

public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException { 
    for (int i = 0; i < values.length; i++) { 
     preparedStatement.setObject(i + 1, values[i]); 
    } 
} 

關於TIMESTAMP問題,只需使用PreparedStatement#setTimestamp()即可。

+0

'String sql =「SELECT col FROM tbl WHERE ID MEMBER OF?」;'如果[你通過一個集合](https://stackoverflow.com/a/34699771/1509264)將工作。 – MT0 2018-01-14 13:16:37