Java CallableStatement
2023. 2. 26. 17:41ㆍJava
프로젝트 내 src 내 javabasic 패키지 내 ObjectSerTest.java
//PS C:\Users\ydbon> sqlplus
//
//SQL*Plus: Release 11.2.0.1.0 Production on 수 3월 9 09:44:19 2022
//
//Copyright (c) 1982, 2010, Oracle. All rights reserved.
//
//사용자명 입력: scott/a1234
//
//다음에 접속됨:
//Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
//With the Partitioning, OLAP, Data Mining and Real Application Testing options
//
//SQL> #객체들을 주고받기위해서는 직렬화과정이필요한데 객체에는 여러가지변수인스턴스들로이루어져있다.
//SP2-0734: "객체들을 ..."(으)로 시작되는 알 수 없는 명령 - 나머지 줄은 무시되었습니다.
//SQL> #그런멤버를스트림에옮기기위해 하나하나씩 변수들을 나열해서 전송해야 한다.
//SP2-0734: "그런멤버를..."(으)로 시작되는 알 수 없는 명령 - 나머지 줄은 무시되었습니다.
//SQL> @직렬화된 객체를 데이타베이스에 저장할수있는데 blob필드에 지정할수있다는것이다.
//SP2-0310: 파일 "직렬화된.sql"을 열 수 없습니다.
//SQL> 클래스만들때serializable을...써야한다
//SP2-0734: "클래스만들..."(으)로 시작되는 알 수 없는 명령 - 나머지 줄은 무시되었습니다.
//SQL> serializable interface를구현해야
//SP2-0734: "serializab..."(으)로 시작되는 알 수 없는 명령 - 나머지 줄은 무시되었습니다.
//SP2-0044: 명령어 목록을 보려면 HELP를
//빠져나가려면 EXIT를 입력하시오.
//SQL> 오라클칼럼에서 다시 가져오려면 역직렬화과정도거쳐야한다.
//SP2-0734: "오라클칼럼..."(으)로 시작되는 알 수 없는 명령 - 나머지 줄은 무시되었습니다.
//SQL> create table object_table(
// 2 no number,
// 3 obj_name varchar2(1000),
// 4 obj_value blob default empty_blob()
// 5 );
//
//테이블이 생성되었습니다.
//
//SQL> create sequence object_ser_seq increment by 1 start with 1;
//
//시퀀스가 생성되었습니다.
package javabasic;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import oracle.sql.BLOB;
public class ObjectSerTest implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
static final String driver_class = "oracle.jdbc.driver.OracleDriver";
static final String connectionURL = "jdbc:oracle:thin:@localhost:1521:orcl";
static final String userId = "scott";
static final String userPassword = "a1234";
static final String getSequenceSQL = "SELECT object_ser_seq.nextval FROM dual";
static final String writeObjSQL = "BEGIN" + " INSERT INTO object_table(no, obj_name, obj_value)"
+ " VALUES(?,?,empty_blob())" + "RETURNING obj_value INTO ?; " + "END;";
// 위의 프로시저에서 empty_blob()는 굳이 안넣어도 된다
// returning obj_value into ? 에서 ?부분은 파라미터로 설정해서 처리할것
// returning obj_value는 obj_value값을 받겠다는 것이다.(물음표)
// obj_value값으로 받아야되는데 이때 받는 변수는 이제 자바에서 처리해야할 타입으로
// OutParameter를 설정하겠다는 의미이다.물음표에는 java.sql.types.BLOB
// 타입으로 요 obj_value값인 empty_blob()값을 받아서 처리하기 위해서
// registerOutParameter로 등록을 해놓는 것이다.프로시저 문을 실행했을때
// 그럼 프로시저에서 어떤 변숫값으로 returning obj_value INTO ?에서 물음표가
// 어떤 변숫값으로 처리가 된다.그 변숫값을 이제 자바에서 받아가지고 처리하기 위해서
// java.sql.Types 패키지에서 BLOB타입으로 등록을 해놓는 것이다.프로시저에서 받는
// 값을 자바에서 처리하겠다.registerOutParameter의 의미다.
// 직렬화된 객체를 불러온다(직렬화된 객체를 저장을 하고 그 저장된 객체를 다시 불러온다.)
static final String readObjSQL = "SELECT obj_value FROM object_table WHERE no = ?";
// 직렬화된 객체를 write하는 메서드,저장한객체의넘버값을반환한다
public static long writeObj(Connection conn, Object obj) throws Exception {
long rec_key = getNextSeqVal(conn);// 시퀀스얻어와서 설정하기
String className = obj.getClass().getName();
CallableStatement stmt = conn.prepareCall(writeObjSQL);
stmt.setLong(1, rec_key);
stmt.setString(2, className);
stmt.registerOutParameter(3, java.sql.Types.BLOB);
stmt.executeUpdate();
// BLOB는 오라클사객체이다
BLOB blob = (BLOB) stmt.getBlob(3);// obj_value의 blob타입을 얻어온다
// 스트림객체를 생성하기,blob와 연결되어 있는 아웃풋스트림이다.
// 이런 스트림을 노드스트림이라고 한다.직접 blob와 연결되어있는 아웃풋스트림이기
// 때문이다.실제 blob에 연결되어 있는 스트림이다.
@SuppressWarnings("deprecation")
OutputStream out = blob.getBinaryOutputStream();
// 아웃풋스트림을 직렬화를 한다.직렬화하는 오브젝트아웃풋스트림을생성해줘야한다
// 직렬화하는 아웃풋스트림
// 노드를 연결하기 위한 브릿지 역할하는 브릿지 스트림역할이다.
ObjectOutputStream oop = new ObjectOutputStream(out);// OutputStream과 연결해서 사용한다.
// 직렬화
oop.writeObject(obj);
oop.flush();
oop.close();
out.close();
stmt.close();
System.out.println("직렬화 완료!!!" + className);
return rec_key;
}
// 직렬화된 객체가 실지 데이타베이스에 저장되는데 이저장되어있는객체를 역으로
// 역직렬화를 시키는 방법. 저장되어있는객체를 반대로 객체화 하는 과정이다.
// 디비에 저장된 객체를 불러오는 read 메소드
public static Object readObj(Connection conn, long rec_key) throws Exception {
PreparedStatement stmt = conn.prepareStatement(readObjSQL);
// 요 해당 rec_key값은 write한후 돌려받은 키값이 된다.이부분은메인에서처리.
stmt.setLong(1, rec_key);
// 수행
ResultSet rs = stmt.executeQuery();
rs.next();// blob객체이므로 blob 객체 스트림을 통해서 얻어오면 되겠다.
// InputStream을 통해서 getBlob에있는 내용을 읽어올수가 있는거죠.
// InputStream 자체가 노드스트림이잖아요.직접 blob로부터연결되있기땜에
// 이 노드스트림을 다시 역직렬화하기위해서는 오브젝트인풋스트림(역직렬화)이 필요하다
InputStream is = rs.getBlob(1).getBinaryStream();// obj_value한개 blob객체의스트림
// 그런데 역직렬화를 통해서 얻어와야 한다.
// ObjectInputStream은 브릿지역할을해준다.is객체를이용해서 브릿지역할해
// 줘야해요.그래야 역직렬화를할수있는것을생성한다.
ObjectInputStream oip = new ObjectInputStream(is);
Object obj = oip.readObject();
// 클래스이름을 구해와서 역직렬화가 제대로 되었는지 확인한다
String className = obj.getClass().getName();
oip.close();
is.close();
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
System.out.println("역직렬화 완료!! " + className);
return obj;
}
// next sequence를 구하는 메소드,sequence의 다음값을 구한다
private static long getNextSeqVal(Connection conn) throws Exception {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(getSequenceSQL);
rs.next();// nextValue값에 커서를 위치시키고 그걸 구해온다.
long rec_key = rs.getLong(1);// 가져온값은nextVal 하나뿐이므로.
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
return rec_key;
}
// 메인 메소드
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Connection conn = null;
System.out.println("JDBC 드라이버 로딩 ->" + driver_class);
Class.forName(driver_class);
// 데이타베이스 연결접속
System.out.println("데이타 베이스 접속 -> " + connectionURL);
conn = DriverManager.getConnection(connectionURL, userId, userPassword);
System.out.println("접속 계정 : " + userId);
conn.setAutoCommit(false);
// 직렬화가능한 클래스의 인스턴스 생성
ObjectSerTest obj = new ObjectSerTest();
// 객체를 직렬화해서 데이타베이스에 쓰는 과정이 필요하다(직렬화가 가능한 오브젝트를 사용해야 한다)
// 직렬화된 객체를 oracle blob 컬럼(필드)에 저장
long rec_key = writeObj(conn, obj);
conn.commit();
System.out.println("직렬화된 객체의 번호 ->" + rec_key + "\n");
System.out.println("객체의 값 ->" + readObj(conn, rec_key));
if (conn != null)
conn.close();
}// main
}
//SQL> select * from object_table;
//
//NO
//----------
//OBJ_NAME
//--------------------------------------------------------------------------------
//OBJ_VALUE
//--------------------------------------------------------------------------------
// 1
//jdbc_prg.ObjectSerTest
//ACED0005737200166A6462635F7072672E4F626A65637453657254657374375076BCD97D00750200
//007870
//
//22
//javabasic.ObjectSerTest
//
//NO
//----------
//OBJ_NAME
//--------------------------------------------------------------------------------
//OBJ_VALUE
//--------------------------------------------------------------------------------
//ACED0005737200176A61766162617369632E4F626A6563745365725465737471DC7119B914F01E02
//00007870
//
//24
//javabasic.ObjectSerTest
//ACED0005737200176A61766162617369632E4F626A65637453657254657374000000000000000102
//00007870
//
//NO
//----------
//OBJ_NAME
//--------------------------------------------------------------------------------
//OBJ_VALUE
//--------------------------------------------------------------------------------
//SQL> #16진수binary형태로 blob타입으로 저장이 된것
실행 결과
JDBC 드라이버 로딩 ->oracle.jdbc.driver.OracleDriver
데이타 베이스 접속 -> jdbc:oracle:thin:@localhost:1521:orcl
접속 계정 : scott
직렬화 완료!!!javabasic.ObjectSerTest
직렬화된 객체의 번호 ->24
역직렬화 완료!! javabasic.ObjectSerTest
객체의 값 ->javabasic.ObjectSerTest@49993335
java.sql.CallableStatement
CallableStatement 는 인터페이스 (규격) 로써 SQL에서 저장된 절차들을 실행하는데에 사용된다.
JDBC API 는 한개의 저장된 절차에 SQL escape(벗어나는 수단, 탈출) 구문을 제공하는데 그러한 탈출 구문은 모든 RDBMS들에서 저장된 절차들이 표준적인 방법으로 호출되어지는 것을 허용한다.
요 탈출 구문은 한개의 결과 파라메터를 포함하는 형식과 포함하지 않는 형식을 가진다.
만약에 사용된다면, 고 결과 파라메터는 반드시 OUT 파라메터(인수)로 등록되어져야만 한다.
다른 파라메터들(인수들)은 입력, 출력, 또는 입출력 둘다로 사용될 수 있다.
IN 파라메터 값들은 PreparedStatement 로부터 이어받은 set 메서드를 이용하면서 설정된다. 모든 OUT 파라메터들의 유형(모양)은 반드시 저장된 절차를 실행하기 전에 등록되어져야만 한다; OUT 파라메터들(인수들)의 값들은 여기서 제공된 get 메서드들을 통해 실행 후에 정보가 끌어내어진다.
'Java' 카테고리의 다른 글
Java - java.sql (0) | 2023.02.27 |
---|---|
Java CharArrayReader class (0) | 2023.02.27 |
Java executeBatch() (0) | 2023.02.26 |
Java ResultSetMetaData (0) | 2023.02.24 |
Java Collections class (0) | 2023.02.21 |