怎么利用MyBatis传List类型参数到数据库存储过程中实现批量插入数据?
MyBatis中参数是List类型时怎么处理?大家都知道MyBatis批处理大量数据是很难做到事务回滚的(事务由Spring管理),都将逻辑写在存储中又是及其头疼的一件事(参数长度也有限制),那么我想的是将参数在后台封装为单个或多个list集合,直接通过MyBatis将此参数传到数据库存储过程中,一来摆脱了MyBatis批量插入数据的诸多限制(例如:不能实时返回主键、foreach标签循环集合长度有限制),二来就是在存储中灵活的控制事务,但是这又会涉及两个问题,MyBatis的xml文件中该怎么封装,利用BaseTypeHandler吗?
对于这个问题,经过一天的研究终于算是跑通了,说一下解决办法:
1.建立数据库表,大家应该都有自己的库表了,所以这一步基本上就可以跳过了。我之所以在这里把库表贴出来是为了让大家对应里面的参数。
数据库表:
[sql]
view plain
copy
create table ZD_UNIT_MENU ( unit_id VARCHAR2(32), menu_id VARCHAR2(32) )
2.在数据库中建立相应的java对象(Oracle中的类型)和数组:
[sql]
view plain
copy
CREATE OR REPLACE TYPE unit_menu_obj
AS OBJECT( unitId VARCHAR2(32), menuId VARCHAR2(32) );
CREATE OR REPLACE TYPE unit_menu_table
AS table OF unit_menu_obj;
3.存储过程:
[sql]
view plain
copy
create or replace procedure save_unit_power(list0
in unit_menu_table,result0
out int)
as sql_bind
varchar(200);
begin FOR i
IN 1 .. list0.
count LOOP sql_bind :=
'insert into ZD_UNIT_MENU(UNIT_ID,MENU_ID) values('''||list0(i).unitId||
''', '''||list0(i).menuId||
''' )';
execute immediate sql_bind;
end loop;
commit; result0 := 1; EXCEPTION
WHEN OTHERS
THEN result0 := -1;
ROLLBACK;
end save_unit_power;
4.再看看mybatis的配置吧:
[html]
view plain
copy
<parameterMap type=
"java.util.Map" id=
"_map"> <parameter property=
"list0" jdbcType=
"ARRAY" javaType=
"java.util.List" mode=
"IN" typeHandler=
"com.zd.util.ListHandler"/> <parameter property=
"result0" jdbcType=
"DECIMAL" javaType=
"java.lang.Integer" mode=
"OUT" /> </parameterMap> <select id=
"addUnitPower" statementType=
"CALLABLE" parameterMap=
"_map"> <![CDATA[ CALL save_unit_power(?,?) ]]> </select>
5.看看我是如何调用的?我直接贴我的server代码了,dao层的就没必要了:
[java]
view plain
copy
List<UnitMenu> list =
new ArrayList<UnitMenu>(); Map<String, Object> _map =
new HashMap<String, Object>(); String[] menuIds = menuTreeIds.split(
","); JSONObject job =
new JSONObject();
int result = -
1;
for(
int i =
0; i < menuIds.length; i++){ UnitMenu um =
new UnitMenu(); um.setMenuId(menuIds[i]); um.setUnitId(unitId); list.add(um); } _map.put(
"list0", list); _map.put(
"result0",
""); unitMenuMapper.addUnitPower(_map); System.out.println(
"================================================_map = "+_map.toString()); result = (Integer)_map.get(
"result0"); System.out.println(
"================================================result = "+result);
6.非常关键的一点儿,细心的人应该会注意到,在mapper.xml配置中,有typeHandler配置,里面配置的实际上是我写的一个类,这个类的作用就是讲java中的list转换成数据库中我们建立的对象和数组,看代码吧:
[java]
view plain
copy
package com.zd.util;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
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 com.zd.model.system.UnitMenu;
public class ListHandler
extends BaseTypeHandler{
@Override public Object getNullableResult(ResultSet arg0, String arg1)
throws SQLException {
return null; }
@Override public Object getNullableResult(CallableStatement arg0,
int arg1)
throws SQLException {
return null; }
@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<UnitMenu> list = (ArrayList<UnitMenu>) o; conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.1.88:1521:orcl",
"tctscm",
"tctscm"); ARRAY array = getArray(conn,
"UNIT_MENU_OBJ",
"UNIT_MENU_TABLE", list); parameterSetter.setArray(i, array); } }
catch (Exception e) { e.printStackTrace(); }
finally{
if(
null != conn){ conn.close(); } } }
@SuppressWarnings(
"rawtypes")
private ARRAY getArray(Connection con,String OracleObj, String Oraclelist, List<UnitMenu> listData)
throws Exception { ARRAY array =
null; ArrayDescriptor desc = ArrayDescriptor.createDescriptor(Oraclelist, con); STRUCT[] structs =
new STRUCT[listData.size()];
if (listData !=
null && listData.size() >
0){ StructDescriptor structdesc =
new StructDescriptor(OracleObj, con);
for (
int i =
0; i < listData.size(); i++){ Object[] result = {listData.get(i).getUnitId(),listData.get(i).getMenuId()}; structs[i] =
new STRUCT(structdesc, con, result); } array =
new ARRAY(desc, con, structs); }
else{ array =
new ARRAY(desc, con, structs); }
return array; } }
转载请注明原文地址: https://ju.6miu.com/read-20548.html