Java中執行存儲過程和函數(web基礎學習筆記十四)

1、概述

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

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

CallableStatement 經常使用方法:數據庫

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

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

void

registerOutParameter(int parameterIndex,int sqlType)函數

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

Type

getType(int parameterIndex)url

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

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

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

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();
            }
            
        }        

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

相關文章
相關標籤/搜索