Java中呼叫Oracle儲存過程及儲存函式
阿新 • • 發佈:2019-01-31
一. 編寫測試所用儲存函式或函式
--1.建立一個帶引數的儲存過程,沒有返回值
--給指定的員工漲100元的工資,並且列印漲錢和漲後的工資
create or replace procedure raisesalary(eno in number)
as
--定義一個變數儲存漲前的薪水
psal emp.sal%type;
begin
--得到員工漲前的薪水
select sal into psal from emp where empno=eno;
--給該員工漲100工資
update emp set sal = sal+100 where empno=eno;
--需不需要commit?
--一般不在儲存過程中或儲存函式中提交
--列印
dbms_output.put_line('漲前薪水:' || psal ||'漲後薪水:'||(psal+100));
end;
/*
如何呼叫:
begin
raisesalary(7839);
raisesalary(7566);
commit;
end;
*/
--2.儲存函式,通過return關鍵字返回員工年薪
--查詢某個員工的年收入
create or replace function getYearMoney (eno in number )
return number
as
--定義變數儲存員工的薪水和獎金
psal emp.sal%type;
pcomm emp.comm%type;
begin
--得到該員工的月薪和獎金
select sal,comm into psal,pcomm from emp where empno=eno;
--直接返回年收入
return psal*12+nvl(pcomm,0);
end;
--3.儲存過程,通過in和out引數控制輸入和輸出
--查詢某個員工的姓名,工資和工作
create or replace procedure getEmpInfo(eno in number,
pename out varchar2,
psal out number,
pjob out varchar2)
as
begin
--得到該員工的姓名,工資,職位
select ename,sal,job into pename,psal,pjob from emp where empno=eno;
end;
/*
呼叫
declare
eno number;
pename varchar2(200);
psal number;
pjob varchar2(200);
begin
eno:=7369;
getEmpInfo(eno,pename,psal,pjob);
dbms_output.put_line('姓名:'|| pename);
dbms_output.put_line('工資:'|| psal);
dbms_output.put_line('職位:'|| pjob);
end;
*/
--4.定義包頭和包體
該包裡面是定義儲存函式和儲存過程,只是未實現,要在包體中實現,有點類似java中抽象類。
--包頭
CREATE OR REPLACE Package mypackage as
type empcursor is ref cursor;--定義儲存過程返回的資料型別,該過程返回遊標,類似集合
procedure queryEmpList(dno in number,empList out empcursor);
end mypackage;
--包體,即包頭中定義的儲存過程或函式的實現
CREATE OR REPLACE Package body mypackage as
procedure queryEmpList(dno in number,empList out empcursor) as
begin
--開啟游標
open empList for select * from emp where deptno=dno;
end queryEmpList;
end mypackage;
二. 測試前準備工作
- 準備jdbc驅動 本測試使用 ojdbc14-10.2.0.4.0.jar
- 準備連線資料庫等相關工具類
package demo.Utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//工具類
public class JDBCUtils {
private static String driver = "oracle.jdbc.OracleDriver";
private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
private static String user = "scott";
private static String password = "tiger";
//註冊資料庫驅動
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
//獲取資料庫連線
public static Connection getConnection() {
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//釋放資料庫的資源
public static void release (Connection conn,Statement st,ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs = null;
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
st = null;
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
}
三. 編寫java類呼叫儲存過程或函式
主要是通過CallableStatement介面進行呼叫
//呼叫儲存過程,getEmpInfo
package demo.oracle;
import java.sql.CallableStatement;
import java.sql.Connection;
import org.junit.Test;
import demo.Utils.JDBCUtils;
import oracle.jdbc.driver.OracleTypes;
public class TestProcedure {
@Test
public void testProcedure() {
String sql = "{call getEmpInfo(?,?,?,?)}";
Connection conn = null;
CallableStatement call = null;
try {
//得到一個連結
conn = JDBCUtils.getConnection();
//通過連結創建出statement
call = conn.prepareCall(sql);
//對於in引數,賦值
call.setInt(1, 7839);
//對於out引數,宣告
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3, OracleTypes.NUMBER);
call.registerOutParameter(4, OracleTypes.VARCHAR);
//執行呼叫
call.execute();
//取出結果
String name = call.getString(2);
double sal = call.getDouble(3);
String job = call.getString(4);
System.out.println(name+"\t"+sal+"\t"+job);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, null);
}
}
}
//呼叫儲存函式,getYearMoney
package demo.oracle;
import java.sql.CallableStatement;
import java.sql.Connection;
import org.junit.Test;
import demo.Utils.JDBCUtils;
import oracle.jdbc.driver.OracleTypes;
public class TestFunction {
@Test
public void testFunction () {
String sql = "{?=call getYearMoney(?)}";
Connection conn = null;
CallableStatement call = null;
try {
//得到一個連結
conn = JDBCUtils.getConnection();
//通過連結創建出statement
call = conn.prepareCall(sql);
//對於輸出引數,宣告
call.registerOutParameter(1, OracleTypes.NUMBER);
//對於輸入引數,賦值
call.setInt(2, 7839);
//執行呼叫
call.execute();
//取出結果
double sals = call.getDouble(1);
System.out.println("年薪為:"+sals);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, null);
}
}
}
//呼叫包中定義的儲存過程,與普通儲存過程區別在於,包中定義儲存過程或儲存函式可以返回遊標,並在java中進行解析,這樣比在java中拿到結果集執行效率略高些。
package demo.oracle;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import demo.Utils.JDBCUtils;
import oracle.jdbc.driver.OracleCallableStatement;
import oracle.jdbc.internal.OracleTypes;
public class TestCursor {
@Test
public void testCursor(){
String sql = "{call mypackage.queryEmpList(?,?)}";
Connection conn = null;
CallableStatement call = null;
ResultSet rs = null;
try {
//得到一個連結
conn = JDBCUtils.getConnection();
//通過連結創建出statement
call = conn.prepareCall(sql);
//對於in引數,賦值
call.setInt(1, 20);
//對於out引數,宣告
call.registerOutParameter(2, OracleTypes.CURSOR);
//執行呼叫
call.execute();
//取出該部門中所有員工的資訊
rs = ((OracleCallableStatement)call).getCursor(2);
while (rs.next()) {
//取出該員工的員工號,姓名,薪水和職位
int empno = rs.getInt("empno");
String name = rs.getString("ename");
double salary = rs.getDouble("sal");
String job = rs.getString("job");
System.out.println(empno+"\t"+name+"\t"+salary+"\t"+job);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, rs);
}
}
}