Java中执行存储过程和函数(web基础学习笔记十四)
一、概述
如果想要執(zhí)行存儲(chǔ)過程,我們應(yīng)該使用 CallableStatement 接口。
CallableStatement 接口繼承自PreparedStatement 接口。所以CallableStatement 接口包含有Statement 接口和PreparedStatement 接口定義的全部方法,但是并不是所有的方法我們都要使用,主要使用的方法有這樣幾個(gè):
CallableStatement 常用方法:
| 返回類型 | 方法簽名 | 說明 |
| boolean | execute() | 執(zhí)行 SQL 語句,如果第一個(gè)結(jié)果是 ResultSet 對(duì) |
| void | registerOutParameter(int parameterIndex,int sqlType) | 按順序位置parameterIndex 將OUT 參數(shù)注冊為 |
| Type | getType(int?parameterIndex) | 根據(jù)參數(shù)的序號(hào)獲取指定的 JDBC 參數(shù)的值。第一 |
我們可以使用execute()方法來執(zhí)行存儲(chǔ)過程。CallableStatement 為所有的數(shù)據(jù)庫提供了一種統(tǒng)一的標(biāo)準(zhǔn)形式調(diào)用存儲(chǔ)過程。所以,你將會(huì)看到我們使用execute()調(diào)用存儲(chǔ)過程的語法與在Oracle 中會(huì)所有不同。
為了獲得存儲(chǔ)過程或函數(shù)的返回值,我們需要使用 registerOutParameter()方法將返回的參數(shù)注冊為JDBC 的類型。 registerOutParameter()方法的第一個(gè)參數(shù)是參數(shù)的序號(hào),第一個(gè)為1,第二個(gè)為2,以此類推。第二個(gè)參數(shù)需要一個(gè)int 值,用來標(biāo)記JDBC 的類型,我們可以使用java.sql.Types 類中的常量來設(shè)置這個(gè)參數(shù)。比如VARCHAR、DOUBLE 等類型。如果類型不夠用,也可以從具體數(shù)據(jù)庫的驅(qū)動(dòng)中尋找合適的類型常量。如果存儲(chǔ)過程或函數(shù)有返回值,這個(gè)方法是必須要調(diào)用的,否則無法得到返回值,甚至?xí)l(fā)生異常。
CallableStatement 接口中定義了很多get 方法,用于獲取存儲(chǔ)過程返回的值,根據(jù)值的類型不同,你可以使用不同get 方法,比如getInt()、getString()、getDouble()等等。
我們看一下使用CallableStatement 接口執(zhí)行存儲(chǔ)過程和函數(shù)的語法格式。
存儲(chǔ)過程:{call <procedure-name>[(<arg1>,<arg2>, ...)]}
函數(shù):{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
如果要調(diào)用存儲(chǔ)過程,則使用第一種語法,就是開頭不帶問號(hào)的語法,call 后面是過程名,
如果沒有參數(shù),可以省略小括號(hào)。
如果要調(diào)用函數(shù),則使用第二種語法,開頭帶有一個(gè)問號(hào)加等號(hào),實(shí)際上這個(gè)問號(hào)就是一個(gè)占位符,這個(gè)問號(hào)總是調(diào)用函數(shù)的第一個(gè)占位符。其它部分與過程的語法相同
二、CallableStatement 執(zhí)行存儲(chǔ)過程
2.1、建立基類
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;}// 關(guān)閉資源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.2、執(zhí)行不帶參但是有返回值的存儲(chǔ)過程
新建類來繼承上面的類也可以繼承,下面建立存儲(chǔ)過程
--查詢emp表記錄數(shù) CREATE OR REPLACE PROCEDURE getEmpCount(v_count OUT NUMBER) AS BEGINSELECT COUNT(*) INTO v_count FROM emp; END;調(diào)用
//執(zhí)行不帶參但是有返回值的存儲(chǔ)過程獲取emp表總記錄數(shù)public int getTotalCountProc(){//定義一個(gè)變量來接收結(jié)果int totalCount=0;//聲明CallableStatement對(duì)象CallableStatement proc=null;String sql="{call getEmpCount(?)}";try {//建立連接 getConnection();//CallableStatement對(duì)象proc=conn.prepareCall(sql);//將數(shù)據(jù)庫對(duì)象數(shù)據(jù)類型注冊為java中的類型proc.registerOutParameter(1, Types.INTEGER);//執(zhí)行 proc.execute();//接收返回值totalCount=proc.getInt(1);} catch (SQLException e) {// TODO Auto-generated catch block e.printStackTrace();}return totalCount;}2.3、執(zhí)行帶參帶返回值的存儲(chǔ)過程
--根據(jù)部門編號(hào)和姓名查詢?nèi)藬?shù) 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; //執(zhí)行帶參帶返回值的存儲(chǔ)過程public int getTotalCountProc1(int deptno,String ename){//定義一個(gè)變量來接收結(jié)果int totalCount=0;//聲明CallableStatement對(duì)象CallableStatement proc=null;String sql="{call getEmpCount(?,?,?)}";//建立連接 getConnection();//CallableStatement對(duì)象try {proc=conn.prepareCall(sql);//設(shè)置占位符//Object [] params={deptno,ename};//只設(shè)置輸入?yún)?shù)即可proc.setInt(1, deptno);proc.setString(2, ename);//proc.setInt(3, totalCount);將數(shù)據(jù)庫對(duì)象數(shù)據(jù)類型注冊為java中的類型,將輸出參數(shù)轉(zhuǎn)換proc.registerOutParameter(3, Types.INTEGER);//執(zhí)行 proc.execute();//獲取結(jié)果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.3、執(zhí)行返回值為游標(biāo)的存儲(chǔ)過程
--查詢員工所有信息 CREATE OR REPLACE PROCEDURE emp_cur(emp_cur OUT SYS_REFCURSOR) AS BEGINOPEN emp_cur FOR SELECT * FROM emp; END; //執(zhí)行返回值為游標(biāo)的存儲(chǔ)過程 游標(biāo)名emp_curpublic List<Emp> getempProc1(){List<Emp> emplist=new ArrayList<Emp>();String sql="{call emp_cur(?) }";//聲明CallableStatement對(duì)象CallableStatement proc=null;//建立連接getConnection();try {//執(zhí)行proc=conn.prepareCall(sql);//注冊類型為數(shù)據(jù)庫游標(biāo)類型proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);//接收結(jié)果集proc.execute();//獲取結(jié)果第一個(gè)對(duì)象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對(duì)象Emp emp=new Emp();//將得到的值添加到對(duì)象中emp.setEmpno(empno);emp.setEname(ename);emp.setJob(job);emp.setMgr(mgr);emp.setHiredate(hiredate);emp.setSal(sal);emp.setComm(comm);emp.setDeptno(deptno);//將對(duì)象添加到集合emplist.add(emp);}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{this.closeResource();if(proc!=null){try {proc.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}return emplist;}以上看出,需要將輸出的參數(shù),和結(jié)果注冊,輸入的參數(shù)不要注冊,
但輸入?yún)?shù)需要設(shè)置占位符
三、執(zhí)行函數(shù)
3.1 、函數(shù)功能為根據(jù)雇員id 返回姓名
CREATE OR REPLACE FUNCTION getename(v_empno NUMBER) RETURN VARCHAR2 AS v_ename VARCHAR2(20);BEGINSELECT ename INTO v_ename FROM emp WHERE empno=v_empno;RETURN v_ename; END; public void getenamefun(int empno){//sqlString 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 blocke.printStackTrace();}}其它的方法與過程一樣,只是多了個(gè)返回值類型
?
轉(zhuǎn)載于:https://www.cnblogs.com/liunanjava/p/4261242.html
總結(jié)
以上是生活随笔為你收集整理的Java中执行存储过程和函数(web基础学习笔记十四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (王道408考研数据结构)第六章图-第四
- 下一篇: [Android]解决Fragment无