天天看點

JDBC實作調用ORACLE存儲過程

1.關于JDBC

(1)什麼是JDBC?

JDBC的全稱是Java Database Connectivity。主要有三個功能:

a.建立與資料庫的連接配接和通路任意表格資料源。

b.發送一個SQL聲明。

c.處理結果。

(2)連接配接資料庫的前提

a.安裝jdk。

b.安裝資料庫。

c.下載下傳對應資料庫的驅動。

(3)資料庫驅動的類型

a.驅動實作JDBC API作為其他資料通路API的一種映射,類似ODBC(Open Database Connectivity 開放資料庫連接配接)。這種類型的驅動通常依賴于本地庫,移植性受到很大的限制。如JDBC-ODBC橋接。注意:JDBC-ODBC橋接被認為是傳統的解決方案。它不支援Oracle資料庫。使用這個驅動最好在您的DBMS(資料庫管理系統)不提供java的JDBC驅動的情況下。

b.驅動程式編寫部分是Java程式語言,部分是本地代碼。這些驅動程式使用本地用戶端庫明确它們連接配接的資料源是哪個。而且,因為本地代碼,移植性也受到了限制。如Oracle的OCI(Oracle Call Interface Oracle回調接口)用戶端。

c.使用純java的客戶機,使用與資料庫無關的協定和中間伺服器通信。中間件伺服器将主機的請求和資料源進行通信。

d.使用純java和實作了網絡協定的驅動程式來明确資料源。用戶端直接和資料源連接配接。

(這個大家可以看看Java關于JDBC的文檔。)

2.先在資料庫建立一個存儲過程,

(1)先建立包

CREATE OR REPLACE PACKAGE LFF_TEST_PACKAGE
is
PROCEDURE LFF_TEST_PROCEDURE(id in number,org out varchar2,po_fhz out varchar2,po_msg out varchar2);
end LFF_TEST_PACKAGE;
           

說明:id是number類型的需要傳入的參數,org,po_phz,po_msg是varchar2類型的傳出的參數。

(2)建立包的實體

create or replace package body LFF_TEST_PACKAGE as
   PROCEDURE LFF_TEST_PROCEDURE(id in number,org out varchar2,po_fhz out varchar2,po_msg out varchar2)
   as
     --定義其他需要使用的變量,需要指定類型及其大小如 username varchar2(20) 而存儲過程名稱括号裡面的輸入和輸出參數是沒有指定類型大小的
     begin
       --select * into org from XX where xxx = id;
       org := 'aaa';
       po_fhz := '1';
       po_msg := '調用成功';
     exception
     when others then
       po_fhz := '-1';
       po_msg := '調用不成功';
   end;
end LFF_TEST_PACKAGE;
           

注意:exception表示出現錯誤時的處理。when others子句用于捕獲命名系統異常和命名的程式員定義異常未處理的所有其餘異常。我自己的了解就是相當于java中的try{}catch(Exception e){}中的exception。

3.利用JDBC調用資料庫的存儲過程。

總的來說,執行任何JDBC的SQL聲明,有以下幾個步驟:

(1)建立連接配接。建立的資料連接配接可以是DBMS,傳統的檔案系統,或者使用相應的JDBC驅動程式的其他資料源。在Java API中對應的是Connection類。

(2)建立聲明。在Java API中有三種類型的聲明:

a.Statement:用于不帶參數實作簡單SQL聲明。

b.PreparedStatement:(繼承Statement),用于可以帶有輸入參數的預編譯SQL聲明。

c.CallableStatement:(繼承PreparedStatement),用于執行帶有輸入輸出參數的存儲過程。

(3)執行語句。Java API中有三種執行方法。

a.execute:使用這個方法可以傳回一個或更多個結果集對象。

b.executeQuery:傳回一個結果集。用于查詢語句。

c.executeUpdate:傳回受到影響的記錄的數目。這個方法用于插入insert,删除delete,或是更新update。

(4)處理結果集對象。通過光标處理ResultSet對象。這個光标不是資料庫中的光标。這個光标是一個指針指向結果集對象中的某一行資料。最初,這個光标位于第一行資料的前面,你可以使用在結果集ResultSet對象中定義的各種各樣的方法移動光标。

(5)關閉連接配接。無論是否抛出異常,在finally中調用close方法。根據先打開後關閉的原則。

/**
 * @date 2017-6-6
 * @author liufeifei
 * @description 測試調用資料庫的存儲過程
 */
public class TestProcedure {

    public static void main(String[] args) {
        //資料庫驅動的名稱
        String driver = "oracle.jdbc.OracleDriver";
        //通路資料庫路徑 localhost表示本機(127.0.0.1),xxx表示資料庫名稱
        String url = "jdbc:oracle:thin:@localhost:1521:xxx";
        //使用者名
        String username = "kfxx";
        //密碼
        String password = "kfxx";
        Connection conn = null;
        CallableStatement statement = null;
        try {
            //加載驅動
            Class.forName(driver);
            //連接配接
            conn = DriverManager.getConnection(url, username, password);
            //請求的存儲過程(包名.存儲過程名稱,四個?表示參數)
            String sql = "{call LFF_TEST_PACKAGE.LFF_TEST_PROCEDURE(?,?,?,?)}";
            statement = conn.prepareCall(sql);
            //傳入的參數
            statement.setInt(,);
            //傳回的參數(oracle.jdbc.OracleTypes.VARCHAR表示傳回參數類型)
            statement.registerOutParameter(,oracle.jdbc.OracleTypes.VARCHAR);
            statement.registerOutParameter(,oracle.jdbc.OracleTypes.VARCHAR);
            statement.registerOutParameter(,oracle.jdbc.OracleTypes.VARCHAR);
            //執行
            statement.execute();
            //拿到傳回的值,我的存儲過程的參數1是傳入參數,2,3,4是傳出參數
            System.out.println(statement.getString() + " "+ statement.getString() + " "+ statement.getString());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
             try { 
                   //關閉連接配接
                   if(statement != null){
                        statement.close();
                   }
                   if(conn != null){
                       conn.close();
                   }
             } catch (SQLException ex1) {
             }
        }
    }
}
           

另外,Statement和PreparedStatement的使用:

(1)這三個都是接口Interface。大家可以去看看JDK的源碼

public interface Statement extends Wrapper {}
public interface PreparedStatement extends Statement {}
public interface CallableStatement extends PreparedStatement {}
           

Statement是用來執行不帶參數的SQL語句。

Connection conn = null;
ResultSet rs = null;
Statement statement = null;
try {
    //加載
    Class.forName(driver);
    //連接配接
    conn = DriverManager.getConnection(url, username, password);
    //設定查詢語句
    statement = conn.createStatement();
    statement.execute("select * from emp");
    //執行查詢
    rs = statement.getResultSet();
    while(rs.next()){               
      System.out.println(rs.getObject()+"==>"+rs.getObject());
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} 
           

PreparedStatement是用來執行帶輸入參數的SQL語句。

Connection conn = null;
ResultSet rs = null;
PreparedStatement statement = null;
try {
      //加載
      Class.forName(driver);
      //連接配接
      conn = DriverManager.getConnection(url, username,password);
      //設定查詢語句
      statement = conn.prepareStatement("select * from emp where ename like ?");
      //設定參數
      statement.setString(,"%S%");
      //執行查詢
      rs = statement.executeQuery();
      while(rs.next()){
           System.out.println(rs.getObject()+"==>"+rs.getObject());
      }
}catch(){   
}