Oracle 資料庫
Oracle 存在許多問題。以下是解決這些問題的方法。
假設你的過程輸出引數是 ref cursor
,你將得到此異常。
java.sql.SQLException:列型別無效:2012
所以在 simpleJdbcCall.declareParameters()
中將 Types.REF_CURSOR
更改為 OracleTypes.CURSOR
****
支援 OracleTypes
如果資料中包含某些列型別,則可能只需要執行此操作。
我遇到的下一個問題是,諸如 oracle.sql.TIMESTAMPTZ
之類的專有型別在 SqlRowSetResultSetExtractor 中導致了這個錯誤:
列的 SQL 型別無效; 巢狀異常是 java.sql.SQLException:列的 SQL 型別無效
所以我們需要建立一個支援 Oracle 型別的 ResultSetExtractor 。
我將在此程式碼後解釋密碼的原因。
package com.boost.oracle;
import oracle.jdbc.rowset.OracleCachedRowSet;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* OracleTypes can cause {@link org.springframework.jdbc.core.SqlRowSetResultSetExtractor}
* to fail due to a Oracle SQL type that is not in the standard {@link java.sql.Types}.
*
* Also, types such as {@link oracle.sql.TIMESTAMPTZ} require a Connection when processing
* the ResultSet; {@link OracleCachedRowSet#getConnectionInternal()} requires a JNDI
* DataSource name or the username and password to be set.
*
* For now I decided to just set the password since changing SpringBoot to a JNDI DataSource
* configuration is a bit complicated.
*
* Created by Arlo White on 2/23/17.
*/
public class OracleSqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet> {
private String oraclePassword;
public OracleSqlRowSetResultSetExtractor(String oraclePassword) {
this.oraclePassword = oraclePassword;
}
@Override
public SqlRowSet extractData(ResultSet rs) throws SQLException, DataAccessException {
OracleCachedRowSet cachedRowSet = new OracleCachedRowSet();
// allows getConnectionInternal to get a Connection for TIMESTAMPTZ
cachedRowSet.setPassword(oraclePassword);
cachedRowSet.populate(rs);
return new ResultSetWrappingSqlRowSet(cachedRowSet);
}
}
某些 Oracle 型別需要 Connection 才能從 ResultSet 獲取列值。TIMESTAMPTZ 是這些型別之一。因此,當呼叫 rowSet.getTimestamp(colIndex)
時,你將獲得以下異常:
引發者:java.sql.SQLException:未在
oracle.jdbc.rowset.OracleCachedRowSet.getTimestamp(OracleCachedRowSet.java)
的 oracle.jdbc.rowset.OracleCachedRowSet.getConnectionInternal(OracleCachedRowSet.java:560)中設定一個或多個身份驗證 RowSet 屬性。 :3717)at org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet.getTimestamp
如果你深入研究此程式碼,你將看到 OracleCachedRowSet 需要密碼或 JNDI DataSource 名稱才能獲得 Connection。如果你更喜歡 JNDI 查詢,只需驗證 OracleCachedRowSet 是否設定了 DataSourceName。
所以在我的服務中,我在密碼中自動裝配並宣告輸出引數,如下所示:
new SqlOutParameter("cursor_param_name", OracleTypes.CURSOR, new OracleSqlRowSetResultSetExtractor(oraclePassword))