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大概就这些了.有什么不对的,欢迎不吝赐教