Mybatis传list参数调用oracle存储过程的解决方法
怎么利用mybatis传list类型参数到数据库存储过程中实现批量插入数据?
mybatis中参数是list类型时怎么处理?大家都知道mybatis批处理大量数据是很难做到事务回滚的(事务由spring管理),都将逻辑写在存储中又是及其头疼的一件事(参数长度也有限制),那么我想的是将参数在后台封装为单个或多个list集合,直接通过mybatis将此参数传到数据库存储过程中,一来摆脱了mybatis批量插入数据的诸多限制(例如:不能实时返回主键、foreach标签循环集合长度有限制),二来就是在存储中灵活的控制事务,但是这又会涉及两个问题,mybatis的xml文件中该怎么封装,利用basetypehandler吗?
对于这个问题,经过一天的研究终于算是跑通了,说一下解决办法:
1.建立数据库表,大家应该都有自己的库表了,所以这一步基本上就可以跳过了。我之所以在这里把库表贴出来是为了让大家对应里面的参数。
数据库表:
create table zd_unit_menu ( unit_id varchar2(32), menu_id varchar2(32) )
2.在数据库中建立相应的java对象(oracle中的类型)和数组:
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.存储过程:
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; --返回结果,执行成功的话返回1 result0 := 1; --捕捉异常,回滚操作 exception when others then result0 := -1;--执行失败的话返回-1 rollback; end save_unit_power;
4.再看看mybatis的配置吧:
<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层的就没必要了:
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转换成数据库中我们建立的对象和数组,看代码吧:
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 { // todo auto-generated method stub return null; } @override public object getnullableresult(callablestatement arg0, int arg1) throws sqlexception { // todo auto-generated method stub 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"); //这里必须得用大写,而且必须要引入一个包,如果不引入这个包的话字符串无法正常转换,包是:orai18n.jar 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; } }
以上所述是小编给大家介绍的mybatis传list参数调用oracle存储过程的解决方法,希望对大家有所帮助
上一篇: ASP.NET数据绑定的记忆碎片实现代码
下一篇: Java数据结构之查找