怎么利用MyBatis傳List類型參數到數據庫存儲過程中實現批量插入數據?

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標簽實現。不用擔心事務,如果報異常是會整體回滾的,前提是你配置了事務。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容