你的位置:首页 > 数据库

[数据库]oracle存储过程入门


http://www.360doc.com/content/14/0728/16/7662927_397682668.shtml


如何使用Mybaits调用数据库中的存储过程,下面以Oracle数据库的为例:

 1.在数据库中创建以下的存储过程:

 

java代码:
 
  1. create or replace procedure pro_hello(p_user_name in varchar2,p_result out varchar2) is  
  2. begin  
  3.   p_result := 'hello,' || p_user_name;  
  4. end;  



 

2.编写SQL映射文件mapper.

 

java代码:
 
  1. <select id="proHello" statementType="CALLABLE">  
  2. <![CDATA[  
  3.     {call pro_hello (#{p_user_name,mode=IN,jdbcType=VARCHAR},#{result,mode=OUT,jdbcType=VARCHAR})}  
  4. ]]>  
  5. </select>  



 

3.编写JAVA代码调用存储过程

 

java代码:
 
  1. public class ProcedureTest {  
  2.           
  3.          public static void main(String[] args) throws IOException {  
  4.             String resource = "mybatis.cfg.
  5.             Reader reader = Resources.getResourceAsReader(resource);  
  6.             SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);  
  7.          
  8.             SqlSession session = ssf.openSession();  
  9.          
  10.            try {  
  11.                  Map<String, String> param = new HashMap<String, String>();  
  12.                  param.put("p_user_name", "zhangsan");  
  13.                  String returnValue = (String) session.selectOne("User.proHello", param);  
  14.                  System.out.println("message=" + param.get("p_user_name"));  
  15.                  System.out.println("result=" + param.get("result"));  
  16.                  System.out.println("returnValue=" + returnValue);  
  17.    
  18.            } catch (Exception e) {  
  19.                 e.printStackTrace();  
  20.            } finally {  
  21.               session.close();  
  22.           }  
  23.        }  
  24. }  



 

4.执行Java代码,控制台输出结果如下:

 

java代码:
 
  1. 2012-03-07 20:36:32,406 DEBUG [java.sql.PreparedStatement] -==>  Executing: {call pro_hello(?,?)}  
  2. 2012-03-07 20:36:32,406 DEBUG [java.sql.PreparedStatement] -==> Parameters: zhangsan(String)  
  3. message=zhangsan  
    1. Mapper.

      Mapper.  <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.

  4. (mybatis 调用存储过程另一种实现)Mybatis默认查询存储过程的返回值是使用参数传来传去的,从参数里获取返回值总让我感觉怪怪的,特别是在使用接口做Dao的时候,破坏了Dao接口方法的统一性。
  5. 然后就有了mybatis-callable,获得方式如下:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <dependencies>
      ...
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-callable</artifactId>
            <version>1.0</version>
        </dependency>
     ...
    </dependencies>



     

     

    配置是这样的:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <? 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时拦截器才会起作用:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <select id="query2" statementType="CALLABLE">
        <![CDATA[
            {call test_proc2(
                #{acResult,mode=OUT,jdbcType=CURSOR,javaType=ResultSet, resultMap=hashMap},
                #{userType},
                #{branchCode}
            )}
        ]]>
    </select>



     

    然后Dao或许是这样的,接口也是一样的:

    ?
    1
    2
    3
    4
    5
    6
    7
    public 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);
    }



     

    ===========================================

    返回单个参数但是不是游标的话就这样

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <select id="query3" statementType="CALLABLE">
        <![CDATA[
            {call test_proc3(
                #{retCode,mode=OUT,jdbcType=INTEGER},
                #{userType},
                #{branchCode}
            )}
        ]]>
    </select>



     

    ?
    1
    2
    3
    4
    5
    6
    7
    public 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);
    }



     

    ===========================================

    返回多个参数,里面啥都有:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <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>



     

    ?
    1
    2
    3
    4
    5
    6
    7
    public 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了。

    ?
    1
    2
    3
    <plugin interceptor="com.github.miemiedev.mybatis.callable.CallableConvertInterceptor">
        <property name="resultHandler" value="com.github.miemiedev.mybatis.callable.handler.SimpleResultHandler"/>
    </plugin>



     

     

    完。