-
008. CallableStatementSsY/Class 2023. 5. 2. 14:16728x90
JDBC
- CallableStatement 설명- CallableStatement
■■■ CallableStatement ■■■ // 호출이 가능한 작업객체~ 개발자로서 많이 사용되지는 않음 // PreparedStatement 를 가장 많이 활용하게 됨 -- 왜냐면 사용하는 것 만으로도 Secure Coding 가능 ----------------------------------------------------------------------------------------------------------- 1. CallableStatement 인터페이스는 모든 DBMS에 대한 표준 방법으로 저장 프로시저(stored procedure) 를 호출하는 방법을 제공하는 인터페이스이며, 호출은 escape 문법으로 작성된다. ----------------------------------------------------------------------------------------------------------- 2. 결과 매개변수를 가지는 형태와 결과 매개변수가 없는 형태(두 가지)이며 OUT 매개변수의 종류인 결과 매개변수는 저장 프로시저에 대한 반환값이다. // ▼ 핵심 ▼ 두 형태 모두 IN 매개변수(입력), OUT 매개변수(출력), INOUT 매개변수(입출력) 를 위해 사용되는 매개변수의 변수 번호를 가지며 『?』는 매개변수의 저장 위치로 나타낸다. ----------------------------------------------------------------------------------------------------------- 3. 형식 및 구조 (JDBC 에서 저장 프로시저 호출을 위한 문법) // 쿼리문을 직접 운용할 필요가 없음 -> 함수나 프로시저가 처리 매개변수가 없는 저장 프로시저 호출 {call procedure_name} IN 매개변수를 넘겨주는 프로시저 호출 {call procedure_name[(?, ?, ...)]} OUT 매개변수를 반환하는 프로시저 호출 / 반환자료형이 존재하는 함수 호출 {? = call procedure_name[(?, ?, ...)]} ----------------------------------------------------------------------------------------------------------- 4. CallableStatement 객체 생성 CallableStatement 객체는 Connection 의 prepareCall() 메소드에 의해 생성된다. 예를 들어, 두 개의 인자값을 가지고 있으며 결과 매개변수가 없는 저장 프로시저 preData 를 호출하는 방법은 다음과 같다. CallableStatement cstmt = conn.prepareCall("{call preData(?, ?)}"); ※ 물음표(『?』)의 위치가 IN, OUT, INOUT 매개변수 중 어떤 것인가 하는 것은 저장 프로시저 prcData 에 의존한다. ----------------------------------------------------------------------------------------------------------- 5. IN, OUT 매개변수 // 매개변수의 정의는 DB 상에서 규정된 것을 사용 -> 이 때문에 사용빈도가 낮음 CallableStatement 객체로 IN 매개변수를 넘겨주는 것은 PreparedStatement 로 부터 상속받은 『setXxx()』 메소드이다. 예를 들어, setFloat() 메소드는 float 값을 넘겨주게 되는 것이다. 만약, 저장 프로시저가 OUT 매개변수를 반환한다면 각 OUT 매개변수의 SQL 형(Type)은 CallblesStatement 객체를 실행할 수 있는 상태가 되기 전까지 등록되어져야 한다. 이는 몇 몇 DBMS 들이 SQL형(Type)을 필요로 하기 때문이며, 이 때, SQL 형(Type) 을 등록하는 것은 registerOutPatrameter() 메소드를 사용하게 된다. 그리고, SQL 구문이 실행되어진 다음에 CallableStatement 의 『getXxx()』 메소드는 매개변수의 값을 검색하며, 사용되는 정확한 『getXxx()』 메소드는 그 매개변수를 위해 등록된 SQL 에 상응하는 자바 형(Type)이다. 즉, registerOutParameter() 메소드는 SQL 타입을 사용하고, getXxx() 메소드는 이것을 자바 타입으로 캐스트(cast) 하는 것이다.
close project / 열 때는 openProject 사용하면 됨
JDBC08
- DBConn 생성
더보기/*================= DBConn.java - throws ===================*/ package com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBConn { private static Connection dbConn; public static Connection getConnection() throws ClassNotFoundException, SQLException { if (dbConn == null) { String url = "jdbc:oracle:thin:@localhost:1521:xe"; String user = "scott"; String pwd = "user"; Class.forName("oracle.jdbc.driver.OracleManager"); dbConn = DriverManager.getConnection(url,user,pwd); } return dbConn; } public static Connection getConnection(String url, String user, String pwd) throws ClassNotFoundException, SQLException { if (dbConn == null) { Class.forName("oracle.jdbc.driver.OracleManager"); dbConn = DriverManager.getConnection(url, user, pwd); } return dbConn; } public static void Close() throws SQLException { if (dbConn != null) { if (!dbConn.isClosed()) { dbConn.close(); } } dbConn = null; } }
SQL DEVELOPER
더보기SELECT USER FROM DUAL; --==>> SCOTT SELECT * FROM TBL_MEMBER ORDER BY SID; --==>> /* 1 별희강 010-1111-1111 2 수인주 010-2222-2222 3 기배리 010-3333-3333 4 하경최 010-4444-4444 5 희정권 010-5555-5555 6 이서최 010-6666-6666 7 상훈문 010-7777-7777 8 준복이 010-8888-8888 */ TRUNCATE TABLE TBL_MEMBER; --==>> Table TBL_MEMBER이(가) 잘렸습니다. SELECT * FROM TBL_MEMBER ORDER BY SID; --==>> 조회결과 없음 --○ CallableStatement 실습을 위한 프로시저 작성 -- 프로시저 명 : PRC_MEMBERINSERT -- 프로시저 기능 : TBL_MEMBER 테이블에 데이터를 입력하는 입력 프로시저 --// 매개변수 이름, 전화번호 받아오면 SID 를 MAX() + 1 로 구성하는 프로시저 CREATE OR REPLACE PROCEDURE PRC_MEMBERINSERT ( V_NAME IN TBL_MEMBER.NAME%TYPE , V_TEL IN TBL_MEMBER.TEL%TYPE ) IS -- 주요 변수 선언 V_SID TBL_MEMBER.SID%TYPE; BEGIN -- 기존 SID 의 최대값 얻어오기 SELECT NVL(MAX(SID),0) INTO V_SID FROM TBL_MEMBER; -- INSERT 구문 INSERT INTO TBL_MEMBER(SID, NAME, TEL) VALUES((V_SID+1), V_NAME, V_TEL); -- 커밋 COMMIT; END; --==>> Procedure PRC_MEMBERINSERT이(가) 컴파일되었습니다. --○ 생성된 프로시저 테스트(정상 작동여부 확인) EXEC PRC_MEMBERINSERT('건우박','010-1111-1111'); --==>> PL/SQL 프로시저가 성공적으로 완료되었습니다. --○ 테이블 조회 SELECT * FROM TBL_MEMBER ORDER BY SID; --==>> 1 건우박 010-1111-1111
- Test001
- DML 쿼리문
/*======================================================= Test001.java - CallableStatement 를 활용한 SQL 구문 전송 실습 =========================================================*/ package com.test; import java.sql.CallableStatement; import java.sql.Connection; import java.util.Scanner; import com.util.DBConn; public class Test001 { public static void main(String[] args) { try { Scanner sc = new Scanner(System.in); Connection conn = DBConn.getConnection(); do { System.out.print("이름 입력(-1 종료) : "); String name = sc.next(); if (name.equals("-1")) break; System.out.print("전화번호 입력 : "); String tel = sc.next(); if (conn != null) { System.out.println("데이터베이스 연결 성공~"); try { // 쿼리문 준비 check //-- PreparedStatement를 상속받아 쿼리문을 먼저 준비해야함 String sql = "{call PRC_MEMBERINSERT(?,?)}"; // CallableStatement 작업 객체 생성 check CallableStatement cstmt = conn.prepareCall(sql); // 매개변수 전달 cstmt.setString(1, name); cstmt.setString(2, tel); //-- Statement들은 executeUpdate, executeQuery 를 사용하는 기준은 동일하다. int result = cstmt.executeUpdate(); if (result > 0) System.out.println("프로시저 호출 및 데이터 입력 완료~"); } catch (Exception e) { System.out.println(e.toString()); } } } while (true); DBConn.Close(); System.out.println("\n데이터베이스 연결 종료..."); System.out.println("프로그램 종료됨..."); } catch (Exception e) { System.out.println(e.toString()); } } }
SQL DEVELOPER
--○ JDBC 의 Test001 실행 후 확인 SELECT * FROM TBL_MEMBER ORDER BY SID; --==>> /* 1 건우박 010-1111-1111 2 연수양 010-2222-2222 3 지혜김 010-3333-3333 4 아현한 010-4444-4444 */
SQL DEVELOPER
--○ CallableStatement 실습을 위한 프로시저 작성 -- 프로시저 명 : PRC_MEMBERSELECT -- 프로시저 기능 : TBL_MEMBER 테이블에 데이터를 읽어오는 입력 프로시저 -- ※ 『SYS_REFCURSOR』 자료형을 이용하여 커서 다루기 --// 오라클에서 기본저긍로 제공하는 커서 CREATE OR REPLACE PROCEDURE PRC_MEMBERSELECT ( VRESULT OUT SYS_REFCURSOR ) IS -- 주요 변수 선언 → 커서 정의(X) BEGIN OPEN VRESULT FOR --FOR 은 각각에 집어넣을 때 SELECT SID, NAME, TEL --┐ FROM TBL_MEMBER --┃-- 이 구문 안에 집어넣는다는 뜻 ORDER BY SID; --┘ --// ※ 외부에서 쓰려고 만든 커서이기 때문에 닫으면 안됨 --CLOSE VRESULT; --// ※ DML 구문이 아니기 때문에 사용하지 않는다. --COMMIT; END; --> Procedure PRC_MEMBERSELECT이(가) 컴파일되었습니다.
- Test002
- Select 쿼리문
/*======================================================= Test002.java - CallableStatement 를 활용한 SQL 구문 전송 실습 =========================================================*/ package com.test; import java.sql.CallableStatement; import java.sql.Connection; import com.util.DBConn; import oracle.jdbc.internal.OracleTypes; public class Test002 { public static void main(String[] args) { try { Connection conn = DBConn.getConnection(); if (conn != null) { System.out.println("데이터베이스 연결 성공~"); try { // 쿼리문 준비 check String sql = "{call PRC_MEMBERSELECT(?)}"; // CallableStatement 작업 객체 생성 check CallableStatement cstmt = conn.prepareCall(sql); // chekck // 프로시저 내부에서 SYS_REFCURSOR 를 사용하고 있기 때문에 // OracleTypes.CURSOR 를 사용하기 위한 등록 과정이 필요한 상황 // 1. Project Explorer 상에서 해당 프로젝트 마우스 우클릭 // > Build Path > Configure Build Path 클릭 // 2. 이후 열리는 대화창에서 Libraries 탭 클릭 // > 우측 Add External Jars 버튼 클릭 // 3. 이 때 열리는 파일 등록창에 // 『ojdbc6.jar』 파일 추가 등록 // 4. 『import oracle.jdbc.internal.OracleTypes;』 구문 추가 등록 /* //--※ Test001 과 비교 Test001 get 이나 set 은 자바에서 사용 -- 내부적으로 오라클에 값을 전달할 때, 오라클은 자료구조를 매핑하는 테이블이 있어 String -> VARCHAR2 로 변환해서 가져옴 그러나 Test002 커서타입으로 넘기는건 오라클에서 제대로확인이 불가능하기 때문에 자바에서 오라클 내부의 타입을 지정해서 건네줌 */ // 매개변수 전달 check // cstmt.registerOutParameter(1, 오라클에서의커서); cstmt.registerOutParameter(1, OracleTypes.CURSOR); } catch (Exception e) { System.out.println(e.toString()); } } } catch (Exception e) { System.out.println(e.toString()); } } }
더보기※ Build Path 설정
- Oracle CURSOR 사용을 위해서왜 registerOutParameter() 을 사용하는지 설명 /*======================================================= Test002.java - CallableStatement 를 활용한 SQL 구문 전송 실습 =========================================================*/ package com.test; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import com.util.DBConn; import oracle.jdbc.internal.OracleTypes; public class Test002 { public static void main(String[] args) throws SQLException { try { Connection conn = DBConn.getConnection(); if (conn != null) { System.out.println("데이터베이스 연결 성공~"); try { // 쿼리문 준비 check String sql = "{call PRC_MEMBERSELECT(?)}"; // CallableStatement 작업 객체 생성 check CallableStatement cstmt = conn.prepareCall(sql); // check // 프로시저 내부에서 SYS_REFCURSOR 를 사용하고 있기 때문에 // OracleTypes.CURSOR 를 사용하기 위한 등록 과정이 필요한 상황 // 1. Project Explorer 상에서 해당 프로젝트 마우스 우클릭 // > Build Path > Configure Build Path 클릭 // 2. 이후 열리는 대화창에서 Libraries 탭 클릭 // > 우측 Add External Jars 버튼 클릭 // 3. 이 때 열리는 파일 등록창에 // 『ojdbc6.jar』 파일 추가 등록 // 4. 『import oracle.jdbc.internal.OracleTypes;』 구문 추가 등록 /* //--※ Test001 과 비교 Test001 get 이나 set 은 자바에서 사용 -- 내부적으로 오라클에 값을 전달할 때, 오라클은 자료구조를 매핑하는 테이블이 있어 String -> VARCHAR2 로 변환해서 가져옴 그러나 Test002 커서타입으로 넘기는건 오라클에서 제대로확인이 불가능하기 때문에 자바에서 오라클 내부의 타입을 지정해서 건네줌 */ // 매개변수 전달 check // cstmt.registerOutParameter(1, 오라클에서의커서); cstmt.registerOutParameter(1, OracleTypes.CURSOR); // 주고 받을 때 cstmt.execute(); // + 수신하는것이 문자 형태로 넘겨 받는것이 아닌 커서라는 객체 자체를 받아오는 것 // 첫번째 파라미터 값으로 넘겨받겠다. // ResultSet 타입으로 받아야 처리 할 수 있는데 가져오는 것은 Object 타입 // 다운 캐스팅! //ResultSet rs = cstmt.getObject(1); ResultSet rs = (ResultSet)cstmt.getObject(1); while (rs.next()) { String sid = rs.getString("SID"); String name = rs.getString("NAME"); String tel = rs.getString("TEL"); /* String str = String.format("%3s %7s %12s", sid, name, tel); System.out.println(str); */ // 위와 동일한 구문 System.out.printf("%3s %7s %12s", sid, name, tel); } rs.close(); cstmt.close(); } catch (Exception e) { System.out.println(e.toString()); } } } catch (Exception e) { System.out.println(e.toString()); } DBConn.Close(); System.out.println("\n데이터베이스 연결 닫힘..."); System.out.println("프로그램 종료됨"); } }
728x90'SsY > Class' 카테고리의 다른 글
[HTML] 002. Eclipse 설정, HTML 관찰(태그 관찰) (1) 2023.05.03 [HTML] 001. HTML 의 개요 , Eclipse 설정 Export-Import 로 기존 설정 가져오기 (0) 2023.05.02 007. PreparedStatement / 성적 처리 프로그램 구현 (0) 2023.05.02 006. DB 연동 직원 관리 프로그램 구현 (해설) (0) 2023.04.28 005. DB 연동 직원 관리 프로그램 구현 (DTO, DAO, PROCESS, MAIN) (0) 2023.04.27