http://www.360doc.com/content/14/0728/16/7662927_397682668.shtml
如何使用Mybaits调用数据库中的存储过程,下面以Oracle数据库的为例:
1.在数据库中创建以下的存储过程:
- create or replace procedure pro_hello(p_user_name in varchar2,p_result out varchar2) is
- begin
- p_result := 'hello,' || p_user_name;
- end;
2.编写SQL映射文件mapper.xml:
- <select id="proHello" statementType="CALLABLE">
- <![CDATA[
- {call pro_hello (#{p_user_name,mode=IN,jdbcType=VARCHAR},#{result,mode=OUT,jdbcType=VARCHAR})}
- ]]>
- </select>
3.编写JAVA代码调用存储过程
- public class ProcedureTest {
- public static void main(String[] args) throws IOException {
- String resource = "mybatis.cfg.xml";
- Reader reader = Resources.getResourceAsReader(resource);
- SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
- SqlSession session = ssf.openSession();
- try {
- Map<String, String> param = new HashMap<String, String>();
- param.put("p_user_name", "zhangsan");
- String returnValue = (String) session.selectOne("User.proHello", param);
- System.out.println("message=" + param.get("p_user_name"));
- System.out.println("result=" + param.get("result"));
- System.out.println("returnValue=" + returnValue);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- session.close();
- }
- }
- }
4.执行Java代码,控制台输出结果如下:
- 2012-03-07 20:36:32,406 DEBUG [java.sql.PreparedStatement] -==> Executing: {call pro_hello(?,?)}
- 2012-03-07 20:36:32,406 DEBUG [java.sql.PreparedStatement] -==> Parameters: zhangsan(String)
- message=zhangsan
-
- Mapper.xml 配置
Mapper.xml 配置
<resultMap type="emp" id="empMap">
<id property="empno" column="empno"/>
<result property="ename" column="ename"/>
<result property="mgr" column="mgr"/>
<result property="job" column="job"/>
<result property="hiredate" column="hiredate"/>
<result property="sal" column="sal"/>
<result property="comm" column="comm"/>
</resultMap>
<!-- 调用存储过程返回结果集 -->
<select id="getEmps" parameterType="java.util.Map" statementType="CALLABLE">
<![CDATA[
call pro_emp(#{emps,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=empMap}) ]]>
</select>
存储过程:
create or replace procedure pro_emp(cur_sys out sys_refcursor)
as
begin
open cur_sys for select empno, ename, job, mgr, hiredate, sal, comm, deptno
from tb_emp;
end;
IOperation接口里的方法 :
public interface IOperation {
void getEmps(Map<String, Object> param);
}
测试类:
public class Mytest {
private SqlSession sqlSession;
private IOperation mapper;@Before
public void before(){
try {
SqlSessionFactory factory=MyBatisUtil.getSqlSessionFactory();
sqlSession=factory.openSession();
mapper=sqlSession.getMapper(IOperation.class);
System.out.println("start");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Test
public void getEmps(){
try {
Map<String, Object> param = new HashMap<String, Object>();
param.put("emps",OracleTypes.CURSOR);
mapper.getEmps(param);
List<Emp> depts =(List<Emp>)param.get("emps");
for (Emp emp : depts) {
System.out.println(emp.getEmpno()+" "+emp.getEname());
}
} catch (Exception e) {
System.out.println("getEmp: "+e.getMessage());
}
}
@After
public void after(){
System.out.println("close");
sqlSession.close();
}
}
结果:
start
DEBUG - Openning JDBC Connection
DEBUG - Created connection 8344960.
DEBUG - ooo Using Connection [oracle.jdbc.driver.T4CConnection@7f5580]
DEBUG - ==> Preparing: call pro_emp(?)
DEBUG - ==> Parameters:
123 liuzan
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
close
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@7f5580]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@7f5580]
DEBUG - Returned connection 8344960 to pool.
- (mybatis 调用存储过程另一种实现)Mybatis默认查询存储过程的返回值是使用参数传来传去的,从参数里获取返回值总让我感觉怪怪的,特别是在使用接口做Dao的时候,破坏了Dao接口方法的统一性。
-
然后就有了mybatis-callable,获得方式如下:
123456789<
dependencies
>
...
<
dependency
>
<
groupId
>com.github.miemiedev</
groupId
>
<
artifactId
>mybatis-callable</
artifactId
>
<
version
>1.0</
version
>
</
dependency
>
...
</
dependencies
>
配置是这样的:
123456789<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!
DOCTYPE
configuration
PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<
configuration
>
<
plugins
>
<
plugin
interceptor
=
"com.github.miemiedev.mybatis.callable.CallableConvertInterceptor"
> </
plugin
>
</
plugins
>
</
configuration
>
创建一个查询,需要注意的是只有statementType为CALLABLE时拦截器才会起作用:
123456789<
select
id
=
"query2"
statementType
=
"CALLABLE"
>
<![CDATA[
{call test_proc2(
#{acResult,mode=OUT,jdbcType=CURSOR,javaType=ResultSet, resultMap=hashMap},
#{userType},
#{branchCode}
)}
]]>
</
select
>
然后Dao或许是这样的,接口也是一样的:
1234567public List<
Map
<String, Object>> query2(String userType, String branchCode){
Map<
String
, Object> params = new HashMap<
String
, Object>();
params.put("userType",userType);
params.put("branchCode",branchCode);
//存储过程只返回一个游标,则使用selectList返回List
return getSqlSession().selectList("db.table.user.query2", params);
}
===========================================
返回单个参数但是不是游标的话就这样
123456789<
select
id
=
"query3"
statementType
=
"CALLABLE"
>
<![CDATA[
{call test_proc3(
#{retCode,mode=OUT,jdbcType=INTEGER},
#{userType},
#{branchCode}
)}
]]>
</
select
>
1234567public Integer query3(String userType, String branchCode){
Map<
String
, Object> params = new HashMap<
String
, Object>();
params.put("userType",userType);
params.put("branchCode",branchCode);
//存储过程只有一个返回值,并且不是游标,则使用selectOne
return getSqlSession().selectOne("db.table.user.query3", params);
}
===========================================
返回多个参数,里面啥都有:
12345678910<
select
id
=
"query"
statementType
=
"CALLABLE"
>
<![CDATA[
{call test_proc(
#{retCode,mode=OUT,jdbcType=INTEGER},
#{acResult,mode=OUT,jdbcType=CURSOR,javaType=ResultSet, resultMap=hashMap},
#{userType},
#{branchCode}
)}
]]>
</
select
>
1234567public Map<
String
, Object> query(String userType, String branchCode){
Map<
String
, Object> params = new HashMap<
String
, Object>();
params.put("userType",userType);
params.put("branchCode",branchCode);
//存储过程只有一个返回值,并且不是游标,则使用selectOne
return getSqlSession().selectOne("db.table.user.query", params);
}
Map中包含所有存储过程输出的结果,Key是存储过程的参数名,按需来取就行了。
=============================================
上面看上去规则有点麻烦,其实用接口做的话就不用考虑是selectList还是selectOne了,直接接收返回值就可以。
=============================================
自己定义结果集的话参考一下SimpleResultHandler的实现就行了,反正把自己实现的按照下面这么配就行了。不配resultHandler的话默认就是SimpleResultHandler了。
123<
plugin
interceptor
=
"com.github.miemiedev.mybatis.callable.CallableConvertInterceptor"
>
<
property
name
=
"resultHandler"
value
=
"com.github.miemiedev.mybatis.callable.handler.SimpleResultHandler"
/>
</
plugin
>
完。