1. 程式人生 > >使用iBatis中報 java.sql.SQLException: 無效的列型別異常

使用iBatis中報 java.sql.SQLException: 無效的列型別異常

1. <!--Content表 插入應的記錄到資料庫中 --> 2. < insert id = "insertContent"   parameterClass = "com.unmi.content" > 3. INSERT INTO PERSON(ID,NAME,SERVICEID) VALUES(#id#,#name#,#serviceid#) 4. </ insert > //三個子段允許為空(null) 1. SqlMapClient sqlMap = SqlMapConfig.getSqlMapInstance();  // as coded above
2. Content content= new Content( 1 ); 3. content.setName( "Unmi" ); 4. // content.setServiceId("123456"); // 注意該行被註釋,serviceid屬性為NULL 5. sqlMap.insert( "content" , content); 部分異常資訊: --- The error occurred in com/unmi/content.xml. 
--- The error occurred while applying a parameter map. 
--- Check the insertPerson-InlineParameterMap. 
--- Check the parameter mapping for the 'serviceid' property. 
--- Cause: java.sql.SQLException : 無效的列型別
Caused by: java.sql.SQLException : 無效的列型別
     at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate( GeneralStatement.java:91 )
     at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert( SqlMapExecutorDelegate.java:442 )
     at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert( SqlMapSessionImpl.java:81 )
     at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.insert( SqlMapClientImpl.java:58 )
     at com.unmi.Client.main( Client.java:33 )
Caused by: java.sql.SQLException : 無效的列型別
//解決方案: 只要去掉 content.setServiceId("123456"); 前的註釋,讓content的三個欄位都不為NULL,才能成功向資料庫中插入記錄。其實content表並沒有任何約束,卻是iBatis在此攔截下來,實是多此一舉。那如果我確實讓某個欄位是NULL值,該怎麼做呢?您只要修改一下對映檔案中預置的SQL語句就行了,告訴iBatis當該欄位出現NULL 值該用什麼值來替代,連線Oracle即使是要求某欄位傳入NULL值時就是插入NULL值也必須要你累述一遍,好討厭的事情。  
 

1. <!-- 插入一條Person對應的記錄到資料庫中 -->  
2. < insert id = "content" parameterClass = "com.unmi.content" > 
3.     INSERT INTO PERSON(ID,NAME,PASSWD) VALUES(#id#,#name#,#SERVICEID:VARCHAR:NULL#)  
4. </ insert >
支援的型別在 java.sql.Types 中列示出來了,我一開始還把上面的 VARCHAR 錯寫成了 VARCHAR2。再比如果你想傳入的 id 為NULL時替換為 0, 你就可以寫成 #id:INTEGER:0#。
原因是 iBatis 是根據引數的當前值的型別(而不是類屬性) 來決定對於這個 PrepairedStatement 設定引數是應該呼叫哪一個版本的 setXxx() 方法(是 String 就呼叫,setString() ,是 int 就呼叫 setInt() 等)。而如果引數值為 null,iBatis 便不知道呼叫哪個 setXxx() 方法,於是在 Oracle 的驅動下就籠統的呼叫 setNull() 方法,然而 Oracle 在對字串型別欄位使用 setNull() 卻是有問題的。因為在配置中就必須指明當前欄位的型別,如 #SERVICEID:VARCHAR:NULL#,當 iBatis 在碰到引數為 null 難以決斷時,但見到這裡的 VARCHAR 選項,它也知道應該用 setString() 方法來給 PrepairedStatement 賦值。至於其中的 NULL,不過是指定引數為 null 時的預設值,顯然,寫成 #SERVICEID:VARCHAR# 就行了,後面的 NULL 是多餘的。 不知你注意到沒有,我們上面的insert標記配置了屬性是 parameterClass, 那如果配置的是 parameterMap 該如何解決因欄位為NULL值的問題呢?這就要求我們在配置 parameterMap標記中可能出現NULL值的引數一定要指定相應的 jdbcType屬性就行。只要不指定nullValue屬性就表示在該表這段中直接記下NULL值。 view source
 
print ?
01. < parameterMap   id = "insert-person-paraMap" class = "com.unmi.content" >
02. < parameter property = "id" />
03. < parameter property = "name" />
04. < parameter property = "SERVICEID"   jdbcType = "VARCHAR" />
05. </ parameterMap >
06. <!-- 插入一條Person對應的記錄到資料庫中 -->
07. < insert id = "insertPerson"   parameterMap = "insert-person-paraMap" >
08.      INSERT INTO CONTENT(ID,NAME,SERVICEID) VALUES(?,?,?)
09. </ insert >