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無法自動處理,
部分詳細內容.可以看下https://www.jianshu.com/p/23d6a0d07a87
https://blog.csdn.net/wlwlwlwl015/article/details/52526630有講解typeHandler的部分源碼,
繼承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();
}
}
}
}
8.差不多就是這些了. 參照帖子https://blog.csdn.net/hzw2312/article/details/8444462
如果沒有在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大概就這些了.有什麼不對的,歡迎不吝賜教