美文网首页
怎么利用MyBatis传List类型参数到数据库存储过程中实现批

怎么利用MyBatis传List类型参数到数据库存储过程中实现批

作者: 威尼斯的泪_e592 | 来源:发表于2017-09-08 13:21 被阅读0次

Oracle版本方案(目前只找到Oracle的解决办法,SQL

Server的欢迎大家补充)

参考博客:Mybatis批处理

参考博客:Oracle存储过程实现JAVA中的LIST输入参数

说明:数据库版本为11g,基本上除了存储过程别的都是相对固定的格式,亲测通过。

第一步:创建两个自建类型

CREATE OR REPLACE TYPE xxxobj AS OBJECT(

aVARCHAR2(10),

bVARCHAR2(10),

cVARCHAR2(50)

);

CREATE OR REPLACE TYPE xxxtable AS TABLE OFxxxobj;

第二步:编写存储过程

CREATE OR REPLACE PROCEDURE xxxprocedure(names IN VARCHAR,xxxlist IN xxxtable )

BEGIN

FOR I IN 1..xxxlist.COUNT LOOP

INSERT INTO xxx VALUES

(

xxxlist(I).a,

xxxlist(I).b,

xxxlist(I).c

);

...

...

...

第三步:java代码

xml文件:

{CALL xxxprocedure (?,?)}

java:编写xxxHandler类,继承BaseTypeHandler并重写setNonNullParameter、getArray

@SuppressWarnings("unchecked")

@Override

public voidsetNonNullParameter(PreparedStatement parameterSetter, int i, Object o,JdbcTypejdbcType) throws SQLException {

Connectionconn = null;

try {

if (null != o) {

List list= (ArrayList) o;

conn =DriverManager.getConnection("jdbc:oracle:thin:xxx", "xxx","xxx");

ARRAY array = getArray(conn,"xxxobj", "xxxtable", list);

parameterSetter.setArray(i,array);

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != conn) {

conn.close();

}

}

}

@SuppressWarnings("rawtypes")

@Override

private Array setNonNullParametergetArray(Connection con, String OracleObj, String Oraclelist, List listData)throws Exception {

ARRAYarray = null;

ArrayDescriptordesc = ArrayDescriptor.createDescriptor(Oraclelist, con);

STRUCT[]structs = new STRUCT[listData.size()];

if (listData != null &&listData.size() > 0) {

StructDescriptor structdesc = newStructDescriptor(OracleObj, con);

for (int i = 0; i < listData.size();i++) {

Object[] result = {((xxxClass)listData.get(i)).getA(),((xxxClass) listData.get(i)).getB(),((xxxClass)listData.get(i)).getC()};

structs[i]= new STRUCT(structdesc, con, result);

}

array = new ARRAY(desc, con, structs);

}else{

array= new ARRAY(desc, con, structs);

}

return array;

}

---------------------------------------------------分割线----------------------------------------------------------

SqlServer版本办法,兼容Oracle(说是办法而不算是方案,这是因为其中包含了一些奇巧淫技,我是这么认为的,上不了台面。)

好了,开始代码,第一步也是唯一的一步:我称之为拆分list

int n=list.size();

while(n>500){

xxxMapper.insertlist.subList(0,500));

list.subList(0, 500).clear();

n=list.size();

}

if(n>0){

xxxMapper.insert(list);

}

简单吧,其中500这个参数却决于你的数据库类型和你的sql对应的参数个数(SqlServer2005的传入参数是限制2200个左右,假如你的sql要向表A(除主键外,3个字段)插入记录,那这个参数就是2200除3取整。而list的subList这个方法相信你也是熟到不能再熟了。另外,insert方法是定义在mapper.xml中的方法,利用foreach标签实现。不用担心事务,如果报异常是会整体回滚的,前提是你配置了事务。

相关文章

网友评论

      本文标题:怎么利用MyBatis传List类型参数到数据库存储过程中实现批

      本文链接:https://www.haomeiwen.com/subject/gmvgjxtx.html