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标签实现。不用担心事务,如果报异常是会整体回滚的,前提是你配置了事务。