2012-08-13 61 views
0

的代碼:彈簧JDBC高球插入失敗:無效的列類型

   jdbcTemplate.update("MERGE INTO app_role_data x USING (select ? name, ? xml FROM dual) d ON (x.app_name = d.name) WHEN MATCHED THEN UPDATE SET x.xml_blob = d.xml WHEN NOT MATCHED THEN INSERT(app_name, xml_blob) VALUES(d.name, d.xml)", 
        new AbstractLobCreatingPreparedStatementCallback(lobHandler) { 
          protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { 
            ps.setString(1, appName); 
            lobCreator.setClobAsString(ps, 2, xmlBlob); 
          } 
        }); 

LobHandler接口是在上下文中注入OracleLobHandler的一個實例。

例外:

Caused by: java.sql.SQLException: Invalid column type 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:9231) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8812) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9534) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:9517) 
    at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:351) 
    at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:216) 
    at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144) 
    at org.springframework.jdbc.core.ArgPreparedStatementSetter.doSetValue(ArgPreparedStatementSetter.java:65) 
    at org.springframework.jdbc.core.ArgPreparedStatementSetter.setValues(ArgPreparedStatementSetter.java:46) 
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:815) 
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:1) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586) 

這是Spring框架3.0.5.RELEASE。

我們的Oracle驅動程序相關的

 <dependency> 
     <groupId>com.oracle</groupId> 
     <artifactId>ojdbc14</artifactId> 
     <version>10.2.0.3.0</version> 
     </dependency> 

表:

SQL> desc app_role_data 
Name      Null? Type 
----------------------------------------- -------- ---------------------------- 
APP_NAME      VARCHAR2(64) 
XML_BLOB      CLOB 

我甚至不知道什麼其他的信息,我可以添加,但我會很高興,如果這樣做我把東西留了下來。

+0

這與查詢簡單爲「INSERT INTO app_role_data(app_name,xml_blob)VALUES(?,?)」 – nsayer 2012-08-13 20:33:17

+0

請注意,這也會因Spring 3.1.1.RELEASE失敗而失敗。我真的不敢相信我是整個Universe中唯一無法使用Spring JDBC 3.x將CLOB插入Oracle 11g數據庫的人。 – nsayer 2012-08-14 17:40:09

+0

使用Oracle 11.2.0.2.0 JDBC驅動程序也會失敗。 – nsayer 2012-08-14 17:55:53

回答

1

事實證明,實行()需要PreparedStatementCallback,而update()方法需要一個PreparedStatementSetter。但是兩者都帶有Object的重載,所以編譯器不會抱怨。

抱怨。那是我一生中的一天,我永遠不會回來。

0

我是有點懷疑這裏的列名

你可以嘗試類似下面你MERGE

select ? as name, ? as xml FROM dual 

但我懷疑,太多,因爲你可以有動態列的方式名稱是通過創建一個動態sql並使用EXECUTE IMMEDIATE執行它。

或者可能是這樣的(不是最好的甲骨文而言) -

jdbcTemplate.update("MERGE INTO app_role_data x USING dual d ON (x.app_name = ?) WHEN MATCHED THEN UPDATE SET x.xml_blob = ? WHEN NOT MATCHED THEN INSERT(app_name, xml_blob) VALUES(?, ?)",...... 
+0

即使查詢只是「INSERT INTO app_role_data(app_name,xml_blob)VALUES(?,?)」 – nsayer 2012-08-13 21:08:40

+0

您可以運行'desc app_role_data'併發布輸出嗎?我正在考慮'CLOB'列正在發生什麼。 – Annjawn 2012-08-13 21:36:03

+0

看起來像你的列'xml_blob'的類型是'BLOB',並且你正在使用'lobCreator.setClobAsString'創建一個'CLOB'。你可以嘗試使用'setBlobAsBytes'創建一個blob實例嗎?然後用它代替。 – Annjawn 2012-08-13 21:46:59