使用mybatis給Oracle儲存過程傳List,陣列型別.
0.不廢話.直接上過程
1.因為Oracle本身是有陣列概念的.我們直接使用Oracle中的陣列,但需要先建立型別,varray也就是Oracle的陣列,100指定長度,of後面指定型別,
CREATE OR REPLACE TYPE tables_array AS VARRAY(100) OF VARCHAR2(32);
2.第二步,建立一個表,進行測試資料,
drop table test;
create table test
(
name varchar2(32)
);
3.第三步,建立一個測試過程.,傳入自定義的陣列型別,使用陣列內部方法.遍歷新增
create or replace procedure t_list_to_p(arr_t in tables_array) is begin for i in arr_t.first .. arr_t.last loop insert into test values(arr_t(i)); end loop; commit; end t_list_to_p;
在這裡擴充套件下Oracle陣列的操作方法以及屬性
COUNT 返回集合中元素的個數 DELETE 刪除集合中所有元素 DELETE(x) 刪除元素下標為x的元素 對VARRAY非法 DELETE(x,y) 刪除元素下標從X到Y的元素 對VARRAY非法 EXIST(x) 如果集合元素x已經初始化,則返回TRUE, 否則返回FALSE EXTEND 在集合末尾新增一個元素 對Index_by非法 EXTEND(x) 在集合末尾新增x個元素 對Index_by非法 EXTEND(x,n) 在集合末尾新增元素n的x個副本 對Index_by非法 FIRST 返回集合中的第一個元素的下標號,對於VARRAY集合始終返回1。 LAST 返回集合中最後一個元素的下標號, 對於VARRAY返回值始終等於COUNT. LIMIT 返回VARRY集合的最大的元素個數 Index_by集合和巢狀表無用 NEXT(x) 返回在第x個元素之後及緊挨著它的元素值,如果x是最後一個元素,返回null. PRIOR(x) 返回在第x個元素之前緊挨著它的元素的值,如果x是第一個元素,則返回null。 TRIM 從集合末端開始刪除一個元素 對於index_by不合法 TRIM(x) 從集合末端開始刪除x個元素
4.plsql中呼叫賦值,這個我找了好久.在這展示下.用於測試過程(指儲存過程)是否好用.只要是怎麼給陣列賦值,如果是物件的話,table_list(able_obj('12')),關於物件型別,我會在寫一篇
declare
-- Non-scalar parameters require additional processing
arr_t tables_array:=tables_array('13','14','15');
begin
-- Call the procedure
t_list_to_p(arr_t => arr_t);
end;
5.到這裡函式這裡就準備好了.至於如何用jdbc測試.就不說了.網上很多,接下來講如何用mybatis進行呼叫.先把mybaitis環境搭建好.這裡就不貼程式碼了.
6.編寫map.xml檔案呼叫,以及對應的介面
void appCurrentRoad(@Param("roads")List<String> roads);
下面的.引數最好都寫上.而typeHandler則是必須的.也是我自定義的一個,
<select id="appCurrentRoad" statementType="CALLABLE" >
call t_list_to_p(
#{roads,jdbcType=ARRAY,javaType=List,typeHandler=com.hollycrm.emscheck.common.util.ArrayTypeHandler,mode=IN}
)
</select>
7.編寫自定義的typeHandler.因為我們在Oracle宣告的自定義陣列.是自定義型別的.所以mybatis無法自動處理,
繼承BaseTypeHandler重寫對應方法
package com.common.util;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//這個註解聲明瞭他是處理jdbc型別的 @MappedTypes()也可以用這個註解指定javaType.進行約束,一般不用
@MappedJdbcTypes(JdbcType.ARRAY)
public class ArrayTypeHandler extends BaseTypeHandler{
@Override
public Object getNullableResult(ResultSet arg0, String arg1)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return null;
}
@Override
public Object getNullableResult(CallableStatement arg0, int arg1)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
//這個方法是將java中的集合型別轉換成資料庫中對應型別.在這裡也就是陣列型別
@SuppressWarnings("unchecked")
@Override
public void setNonNullParameter(java.sql.PreparedStatement parameterSetter, int i,
Object o, JdbcType jdbcType) throws SQLException {
Connection conn = null;
try {
if(null != o){
List<String> list = (ArrayList<String>) o;
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost", "test", "test");
//這裡必須得用大寫,而且必須要引入一個包,如果不引入這個包的話字串無法正常轉換,包是:orai18n.jar(這個並沒試過)
//這個應該是封裝的一個轉換方法吧.不是很清楚
ArrayDescriptor arrayDes = ArrayDescriptor.createDescriptor("TABLES_ARRAY",conn);
//這裡是宣告一個數據庫的陣列型別
ARRAY array = new ARRAY(arrayDes,conn,list.toArray());
parameterSetter.setArray(i, array);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
if(null != conn){
conn.close();
}
}
}
}
如果沒有在Handler中註釋jdbcType也可在這裡設定
Xml程式碼
<typeHandlers>
<typeHandler javaType="list" <!--jdbcType="ARRAY"--> handler="com.package.MyHandler"/>
</typeHandlers>
9.最後在總結下遇到的錯誤
這個錯誤是我在沒有指定@MappedJdbcTypes(JdbcType.ARRAY)這個註解的時候丟擲的.在有就是各引數是否對應,如最後的mode是否是in 或者out 或者inout型別
ORA-03115: unsupported network datatype or representation 不支援的網路資料型別或表示
最開始的錯誤.在沒有自定義TypeHandler時
TypeException: Could not set parameters for mapping: ParameterMapping{property='roads', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null',expression='null'..SQLException: 無效的列型別
10.ok大概就這些了.有什麼不對的,歡迎不吝賜教