JDBC를 사용하여 저장 프로시저에서 Oracle 테이블 유형 가져오기
저는 JDBC를 사용하여 Oracle 저장 프로시저/함수에서 테이블 데이터를 가져오는 다양한 방법을 이해하려고 합니다.여섯 가지 방법은 다음과 같습니다.
- 절차스키마 수준 테이블 유형을 OUT 매개 변수로 반환
- 프로시저 패키지 수준 테이블 유형을 OUT 매개 변수로 반환
- 프로시저 패키지 수준 커서 유형을 OUT 매개 변수로 반환
- 함수:스키마 수준 테이블 유형 반환
- 함수패키지 수준 테이블 유형 반환
- 함수패키지 수준 커서 유형 반환
다음은 PL/SQL의 몇 가지 예입니다.
-- schema-level table type
CREATE TYPE t_type AS OBJECT (val VARCHAR(4));
CREATE TYPE t_table AS TABLE OF t_type;
CREATE OR REPLACE PACKAGE t_package AS
-- package level table type
TYPE t_table IS TABLE OF some_table%rowtype;
-- package level cursor type
TYPE t_cursor IS REF CURSOR;
END library_types;
-- and example procedures:
CREATE PROCEDURE p_1 (result OUT t_table);
CREATE PROCEDURE p_2 (result OUT t_package.t_table);
CREATE PROCEDURE p_3 (result OUT t_package.t_cursor);
CREATE FUNCTION f_4 RETURN t_table;
CREATE FUNCTION f_5 RETURN t_package.t_table;
CREATE FUNCTION f_6 RETURN t_package.t_cursor;
JDBC를 통해 3, 4, 6을 호출했습니다.
// Not OK: p_1 and p_2
CallableStatement call = connection.prepareCall("{ call p_1(?) }");
call.registerOutParameter(1, OracleTypes.CURSOR);
call.execute(); // Raises PLS-00306. Obviously CURSOR is the wrong type
// OK: p_3
CallableStatement call = connection.prepareCall("{ call p_3(?) }");
call.registerOutParameter(1, OracleTypes.CURSOR);
call.execute();
ResultSet rs = (ResultSet) call.getObject(1); // Cursor results
// OK: f_4
PreparedStatement stmt = connection.prepareStatement("select * from table(f_4)");
ResultSet rs = stmt.executeQuery();
// Not OK: f_5
PreparedStatement stmt = connection.prepareStatement("select * from table(f_5)");
stmt.executeQuery(); // Raises ORA-00902: Invalid data type
// OK: f_6
CallableStatement call = connection.prepareCall("{ ? = call f_6 }");
call.registerOutParameter(1, OracleTypes.CURSOR);
call.execute();
ResultSet rs = (ResultSet) call.getObject(1); // Cursor results
그래서 분명히, 저는 이해하는데 어려움을 겪고 있습니다.
- 저장 프로시저의 OUT 매개 변수에서 스키마 수준 및 패키지 수준 테이블 유형을 검색하는 방법
- 저장된 함수에서 패키지 수준 테이블 유형을 검색하는 방법
모든 사용자가 항상 테이블 형식 대신 커서를 사용하기 때문에 이에 대한 설명서를 찾을 수 없습니다.가능하지 않아서일까요?그러나 테이블 유형은 공식적으로 정의되고 사전 보기(최소한 스키마 수준 테이블 유형)를 사용하여 검색할 수 있기 때문에 선호합니다.
참고: 분명히, 저는 OUT 매개 변수와 패키지 레벨 테이블 유형을 반환하는 래퍼 함수를 작성할 수 있습니다.하지만 저는 깨끗한 해결책이 더 좋습니다.
Java에서 PLSQL 개체(사례 2 및 5 = 패키지 수준 개체)에 액세스할 수 없습니다. "오라클 저장 프로시저에서 어레이를 전달합니다."를 참조하십시오.그러나 SQL 유형(사례 1 및 4)에 액세스할 수 있습니다.
PL/SQL에서 Java로 OUT 매개 변수를 가져오려면 OracleCallableStatement를 사용하여 Tom Kyte의 스레드 중 하나에 설명된 방법을 사용할 수 있습니다.VARCHAR 테이블 대신 Object 테이블을 검색하는 중이므로 코드에 추가 단계가 있습니다.
다음은 SQL 개체 표를 사용한 데모입니다. 먼저 설정하십시오.
SQL> CREATE TYPE t_type AS OBJECT (val VARCHAR(4));
2 /
Type created
SQL> CREATE TYPE t_table AS TABLE OF t_type;
2 /
Type created
SQL> CREATE OR REPLACE PROCEDURE p_sql_type (p_out OUT t_table) IS
2 BEGIN
3 p_out := t_table(t_type('a'), t_type('b'));
4 END;
5 /
Procedure created
실제 Java 클래스(사용)dbms_output.put_line
SQL에서 호출할 것이기 때문에 로그에 기록합니다.System.out.println
Java에서 호출된 경우):
SQL> CREATE OR REPLACE
2 AND COMPILE JAVA SOURCE NAMED "ArrayDemo"
3 as
4 import java.sql.*;
5 import oracle.sql.*;
6 import oracle.jdbc.driver.*;
7
8 public class ArrayDemo {
9
10 private static void log(String s) throws SQLException {
11 PreparedStatement ps =
12 new OracleDriver().defaultConnection().prepareStatement
13 ( "begin dbms_output.put_line(:x); end;" );
14 ps.setString(1, s);
15 ps.execute();
16 ps.close();
17 }
18
19 public static void getArray() throws SQLException {
20
21 Connection conn = new OracleDriver().defaultConnection();
22
23 OracleCallableStatement cs =
24 (OracleCallableStatement)conn.prepareCall
25 ( "begin p_sql_type(?); end;" );
26 cs.registerOutParameter(1, OracleTypes.ARRAY, "T_TABLE");
27 cs.execute();
28 ARRAY array_to_pass = cs.getARRAY(1);
29
30 /*showing content*/
31 Datum[] elements = array_to_pass.getOracleArray();
32
33 for (int i=0;i<elements.length;i++){
34 Object[] element = ((STRUCT) elements[i]).getAttributes();
35 String value = (String)element[0];
36 log("array(" + i + ").val=" + value);
37 }
38 }
39 }
40 /
Java created
이제 그만하자꾸나:
SQL> CREATE OR REPLACE
2 PROCEDURE show_java_calling_plsql
3 AS LANGUAGE JAVA
4 NAME 'ArrayDemo.getArray()';
5 /
Procedure created
SQL> EXEC show_java_calling_plsql;
array(0).val=a
array(1).val=b
아래 항목도 사용할 수 있습니다.
public List<EmployeeBean> fetchDataFromSPForRM(String sInputDate) {
List<EmployeeBean> employeeList = new ArrayList<EmployeeBean>();
Connection dbCon = null;
ResultSet data = null;
CallableStatement cstmt = null;
try {
dbCon = DBUtil.getDBConnection();
String sqlQuery = "{? = call PKG_HOLD_RELEASE.FN_RM_PDD_LIST()}";
cstmt = dbCon.prepareCall(sqlQuery);
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
data = (ResultSet) cstmt.getObject(1);
while(data.next()){
EmployeeBean employee = new EmployeeBean();
employee.setEmpID(data.getString(1));
employee.setSubBusinessUnitId((Integer)data.getObject(2));
employee.setMonthOfIncentive((Integer)data.getObject(3));
employee.setPIPStatus(data.getString(5));
employee.setInvestigationStatus(data.getString(6));
employee.setEmpStatus(data.getString(7));
employee.setPortfolioPercentage((Integer)data.getObject(8));
employee.setIncentive((Double)data.getObject(9));
employee.setTotalSysemHoldAmt((Double)data.getObject(10));
employee.setTotalManualHoldAmt((Double)data.getObject(11));
employeeList.add(employee);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(data != null){
data.close();
data = null;
}
if(cstmt != null){
cstmt.close();
cstmt = null;
}
if(dbCon != null){
dbCon.close();
dbCon = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return employeeList;
}
언급URL : https://stackoverflow.com/questions/6410452/fetch-oracle-table-type-from-stored-procedure-using-jdbc
'programing' 카테고리의 다른 글
Firebase에서 모든 노드 데이터를 로드하지 않고 노드의 자식 수를 가져올 수 있는 방법이 있습니까? (0) | 2023.07.04 |
---|---|
C에서 사용 가능한 스택 크기 확인 중 (0) | 2023.07.04 |
Spring Boot/Angular 4 - 앱 내 라우팅이 서버를 강타합니다. (0) | 2023.07.04 |
상하좌우 이동 및 확대/축소 (0) | 2023.07.04 |
printf를 사용하여 0 뒤에 오는 경우 소수점 이하의 자리 없이 부동 소수점 이하의 형식 지정 (0) | 2023.07.04 |