Java中執行存儲過程和函數

裝載於:http://www.cnblogs.com/liunanjava/p/4261242.html

1、概述

若是想要執行存儲過程,咱們應該使用 CallableStatement 接口。html

CallableStatement 接口繼承自PreparedStatement 接口。因此CallableStatement 接口包含有Statement 接口和PreparedStatement 接口定義的所有方法,可是並非全部的方法咱們都要使用,主要使用的方法有這樣幾個:java

CallableStatement 經常使用方法:sql

返回類型 方法簽名 說明
boolean execute()

執行 SQL 語句,若是第一個結果是 ResultSet 對 象,則返回 true;若是第一個結果是更新計數或者沒 有結果,則返回 false數據庫

void

registerOutParameter(int parameterIndex,int sqlType)oracle

按順序位置parameterIndex 將OUT 參數註冊爲 JDBC 類型sqlType,sqlType 爲Types 類中的常量函數

Type

getType(int parameterIndex)this

根據參數的序號獲取指定的 JDBC 參數的值。第一 個參數是 1,第二個參數是 2,依此類推url

咱們可使用execute()方法來執行存儲過程。CallableStatement 爲全部的數據庫提供了一種統一的標準形式調用存儲過程。因此,你將會看到咱們使用execute()調用存儲過程的語法與在Oracle 中會全部不一樣。spa

爲了得到存儲過程或函數的返回值,咱們須要使用 registerOutParameter()方法將返回的參數註冊爲JDBC 的類型。 registerOutParameter()方法的第一個參數是參數的序號,第一個爲1,第二個爲2,以此類推。第二個參數須要一個int 值,用來標記JDBC 的類型,咱們可使用java.sql.Types 類中的常量來設置這個參數。好比VARCHAR、DOUBLE 等類型。若是類型不夠用,也能夠從具體數據庫的驅動中尋找合適的類型常量。若是存儲過程或函數有返回值,這個方法是必需要調用的,不然沒法獲得返回值,甚至會發生異常。code

CallableStatement 接口中定義了不少get 方法,用於獲取存儲過程返回的值,根據值的類型不一樣,你可使用不一樣get 方法,好比getInt()、getString()、getDouble()等等。 咱們看一下使用CallableStatement 接口執行存儲過程和函數的語法格式。

存儲過程:{call <procedure-name>[(<arg1>,<arg2>, ...)]} 函數:{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}

若是要調用存儲過程,則使用第一種語法,就是開頭不帶問號的語法,call 後面是過程名, 若是沒有參數,能夠省略小括號。

若是要調用函數,則使用第二種語法,開頭帶有一個問號加等號,實際上這個問號就是一個佔位符,這個問號老是調用函數的第一個佔位符。其它部分與過程的語法相同

2、CallableStatement 執行存儲過程

2.一、創建基類

複製代碼
package com.pb.emp.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.pb.emp.untily.ConfigManager; public class BaseDao { protected Connection conn; protected PreparedStatement ps; protected ResultSet rs; //創建鏈接 public boolean getConnection(){ String driver=ConfigManager.getInstance().getString("jdbc.driver_class"); String url=ConfigManager.getInstance().getString("jdbc.connection.url"); String username=ConfigManager.getInstance().getString("jdbc.connection.username"); String password=ConfigManager.getInstance().getString("jdbc.connection.password"); try { Class.forName(driver); conn=DriverManager.getConnection(url,username, password); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block  e.printStackTrace(); return false; } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); return false; } return true; } //增長,修改,刪除 public int executeUpdate(String sql, Object[] params){ getConnection(); int updateRow=0; try { ps=conn.prepareStatement(sql); //填充佔位符 for(int i=0;i<params.length;i++){ ps.setObject(i+1, params[i]); } updateRow = ps.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); } return updateRow; } // //查詢 public ResultSet executeSQL(String sql, Object[] params){ getConnection(); try { ps=conn.prepareStatement(sql); //填充佔位符 for(int i=0;i<params.length;i++){ ps.setObject(i+1, params[i]); } rs = ps.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); } return rs; } // 關閉資源 public boolean closeResource() { if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); return false; } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); return false; } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); return false; } } return true; } }
複製代碼

2.二、執行不帶參可是有返回值的存儲過程

新建類來繼承上面的類也能夠繼承,下面創建存儲過程

--查詢emp表記錄數 CREATE OR REPLACE PROCEDURE getEmpCount(v_count OUT NUMBER) AS BEGIN SELECT COUNT(*) INTO v_count FROM emp; END;

調用

複製代碼
//執行不帶參可是有返回值的存儲過程獲取emp表總記錄數 public int getTotalCountProc(){ //定義一個變量來接收結果 int totalCount=0; //聲明CallableStatement對象 CallableStatement proc=null; String sql="{call getEmpCount(?)}"; try { //創建鏈接  getConnection(); //CallableStatement對象 proc=conn.prepareCall(sql); //將數據庫對象數據類型註冊爲java中的類型 proc.registerOutParameter(1, Types.INTEGER); //執行  proc.execute(); //接收返回值 totalCount=proc.getInt(1); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); } return totalCount; }
複製代碼

2.三、執行帶參帶返回值的存儲過程

複製代碼
--根據部門編號和姓名查詢人數 CREATE OR REPLACE PROCEDURE getEmpCount(v_deptno NUMBER, v_ename VARCHAR2,v_count OUT NUMBER) AS BEGIN SELECT COUNT(*) INTO v_count FROM emp WHERE ename LIKE '%'||v_ename||'%' AND deptno=v_deptno; END;
複製代碼
複製代碼
//執行帶參帶返回值的存儲過程 public int getTotalCountProc1(int deptno,String ename){ //定義一個變量來接收結果 int totalCount=0; //聲明CallableStatement對象 CallableStatement proc=null; String sql="{call getEmpCount(?,?,?)}"; //創建鏈接  getConnection(); //CallableStatement對象 try { proc=conn.prepareCall(sql); //設置佔位符 //Object [] params={deptno,ename}; //只設置輸入參數便可 proc.setInt(1, deptno); proc.setString(2, ename); //proc.setInt(3, totalCount); ////將數據庫對象數據類型註冊爲java中的類型,將輸出參數轉換 proc.registerOutParameter(3, Types.INTEGER); //執行  proc.execute(); //獲取結果 totalCount=proc.getInt(3); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); }finally{ this.closeResource(); if(proc!=null){ try { proc.close(); } catch (SQLException e) { // TODO Auto-generated catch block  e.printStackTrace(); } } } return totalCount; }
複製代碼

2.三、執行返回值爲遊標的存儲過程

--查詢員工全部信息 CREATE OR REPLACE PROCEDURE emp_cur(emp_cur OUT SYS_REFCURSOR) AS BEGIN OPEN emp_cur FOR SELECT * FROM emp; END;
複製代碼
    //執行返回值爲遊標的存儲過程 遊標名emp_cur public List<Emp> getempProc1(){ List<Emp> emplist=new ArrayList<Emp>(); String sql="{call emp_cur(?) }"; //聲明CallableStatement對象 CallableStatement proc=null; //創建鏈接 getConnection(); try { //執行 proc=conn.prepareCall(sql); //註冊類型爲數據庫遊標類型 proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR); //接收結果集 proc.execute(); //獲取結果第一個對象 rs=(ResultSet) proc.getObject(1); while(rs.next()){ int empno=rs.getInt("empno"); String ename=rs.getString("ename"); String job=rs.getString("job"); int mgr=rs.getInt("mgr"); Date hiredate=rs.getDate("hiredate"); double sal=rs.getDouble("sal"); double comm=rs.getDouble("comm"); int deptno=rs.getInt("deptno"); //聲明Emp對象 Emp emp=new Emp(); //將獲得的值添加到對象中 emp.setEmpno(empno); emp.setEname(ename); emp.setJob(job); emp.setMgr(mgr); emp.setHiredate(hiredate); emp.setSal(sal); emp.setComm(comm); emp.setDeptno(deptno); //將對象添加到集合 emplist.add(emp); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ this.closeResource(); if(proc!=null){ try { proc.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return emplist; }
複製代碼

以上看出,須要將輸出的參數,和結果註冊,輸入的參數不要註冊,

但輸入參數須要設置佔位符

3、執行函數

3.1 、函數功能爲根據僱員id 返回姓名

複製代碼
CREATE OR REPLACE FUNCTION getename(v_empno NUMBER) RETURN VARCHAR2 AS v_ename VARCHAR2(20); BEGIN SELECT ename INTO v_ename FROM emp WHERE empno=v_empno; RETURN v_ename; END;
複製代碼
複製代碼
public void getenamefun(int empno){ //sql String ename=""; String sql="{?=call getename(?)}"; CallableStatement fun=null; getConnection(); try { fun=conn.prepareCall(sql); fun.setInt(2, empno); fun.registerOutParameter(1, Types.VARCHAR); fun.execute(); ename=fun.getString(1); System.out.println(ename); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 
複製代碼

其它的方法與過程同樣,只是多了個返回值類型

相關文章
相關標籤/搜索