본문 바로가기
인천일보아카데미/- 학습일지

[학습일지]JAVA교육일지 73일차 (SERVER)⭐

by w1z 2022. 7. 13.

1. PreparedStatement 클래스

2. CallableStatement 클래스


1. PreparedStatement 클래스

[ Statement & PreparedStatement ]

1) Statement

  - SQL 구문을 실행하는 역할

  - 스스로는 SQL 구문 이해 못함(구문해석 X) -> 전달역할

  - 정적 쿼리 (매개 변수가 없는 쿼리)

  - 코드가 간단하다.

 

2) PreparedStatement

  - Statement 클래스의 기능 향상

  - 동적 쿼리 (매개 변수가 있는 쿼리)

  - 코드 안정성 높음. 가독성 높음.

  - 코드량이 증가 -> 매개변수를 set해줘야하기 때문에..

 

[ PreparedStatement 예제 1 ]

- 미리 오라클 SQL-Developer에서 만들어놓은 tblAddress 테이블에 PreparedStatement를 이용해서 데이터 추가하기

public static void main(String[] args) {

	String name = "호랑이";
	int age = 25;
	String gender = "f";
	String address = "서울시 강남구 대치동";

	Connection conn = null;
	PreparedStatement stat = null;
    
    try {
    	
        // SQL > '?' > 오라클 매개변수(오라클 문법) == String.format()과 유사한 역할
    	String sql = "insert into tblAddress(seq, name, age, gender, address) "
					+ "values(seqAddress.nextval, ?, ?, ?, ?)";
                    
        conn = DBUtil.open();
        stat = conn.prepareStatement(sql);
        
        stat.setString(1, name);
        stat.setInt(2, age);
        stat.setString(3, gender);
        stat.setString(4, address);
        
        System.out.println(stat.executeUpdate());
        
    } catch (Exception e) {
        e.printStackTrace();
    }

}

 

- 결과

DB를 SELECT로 확인 결과 데이터가 정상적으로 들어간 모습 

 

[ PreparedStatement 예제 2 ]

- 사용자가 직접 입력한 데이터의 정보를 가져오기

public static void main(String[] args) {

    Connection conn = null;
    PreparedStatement stat = null;
    ResultSet rs = null;
    
    try {
    
        String sql = "select * from tblAddress where name = ?";
        
        conn = DBUtil.open();
        stat = conn.prepareStatement(sql);
        
        Scanner scan = new Scanner(System.in);
        System.out.print("이름: ");
        String name = scan.nextLine();
        
        stat.setString(1, name);
        
        rs = stat.executeQuery();
        
        while ( rs.next() ) {
            System.out.println(rs.getString("name"));
            System.out.println(rs.getString("gender"));
            System.out.println(rs.getString("address"));
        }
        
        rs.close();
        stat.close();
        conn.close();
    
    } catch (Exception e) {
        e.printStackTrace();
    }

}

 

- 결과

DB에 들어가있는 호랑이를 대상으로 입력시 해당 정보 출력

 

2. CallableStatement

[ 정의 ]

- PreparedStatement를 확장하고 출력 및 입력/출력 매개변수에 대한 지원을 제공한다. ( PreparedStatement 와 유사하다. )

- SQL문을 사용하여 저장 프로시저를 호출할 수 있도록 한다.

- 리턴값을 가질 수 있다.

 

[ CallableStatement 예제 1 - 매개변수 X ]

- 프로시저 (SQL)

CREATE OR REPLACE PROCEDURE proc_m1
IS
BEGIN
    DELETE FROM tblAddress;
END;
SELECT * FROM tblAddress;

 

- Java

Connection conn = null;
CallableStatement stat = null;

try {

    String sql = "{ call proc_m1 }";
    
    conn = DBUtil.open(); // DB연결
    stat = conn.prepareCall(sql);
    
    System.out.println(stat.executeUpdate());
    
    stat.close();
    conn.close();

} catch (Exception e) {
    e.printStackTrace();
}

 

- 결과

Java 컴파일 시 정상 작동시 println으로 콘솔에 1이 출력되며, Oracle DB 확인 결과 delete 된 결과를 볼 수 있다. 

 

[ CallableStatement 예제 2 - 매개변수 O ]

- 프로시저 (SQL)

CREATE OR REPLACE PROCEDURE PROC_M2(
    PNAME IN VARCHAR2,
    PAGE IN NUMBER,
    PGENDER IN VARCHAR2,
    PADDRESS IN VARCHAR2
)
IS
BEGIN
    
   INSERT INTO TBLADDRESS(SEQ, NAME, AGE, GENDER, ADDRESS) 
        VALUES(SEQADDRESS.NEXTVAL, PNAME, PAGE, PGENDER, PADDRESS);
    
END PROC_M2;

 

- Java

Connection conn = null;
CallableStatement stat = null;
		
try {
			
	String sql = "{ call proc_m2(?,?,?,?) }";
			
	conn = DBUtil.open();
	stat = conn.prepareCall(sql);
			
	stat.setString(1, "홍길동");
	stat.setString(2, "20"); // number로 들어갈지 varchar2로 들어갈지는 jdbc가 알아서 해줌
	stat.setString(3, "m");
	stat.setString(4, "서울시 강남구 역삼동");
			
	stat.executeUpdate();
			
	System.out.println("완료");
			
	stat.close();
	conn.close();
			
} catch (Exception e) {
	e.printStackTrace();
}

 

- 결과

비어있던 DB에 만들어둔 SQL 프로시저 실행문을 Java로 실행 후 DB 확인 결과 데이터가 올바르게 들어간걸 볼 수 있다.

 

[ CallableStatement 예제 3 - 프로시저의 아웃 파라미터 받기 ]

- 프로시저(SQL)

CREATE OR REPLACE PROCEDURE proc_m3(
    pname IN VARCHAR2,
    PAGE IN NUMBER,
    pgender IN VARCHAR2,
    paddress IN VARCHAR2,
    presult OUT NUMBER
)
IS
BEGIN
    
   INSERT INTO tbladdress(seq, NAME, age, gender, address) 
        VALUES(seqaddress.NEXTVAL, pname, PAGE, pgender, paddress);
    
    presult := 1;

EXCEPTION
    WHEN OTHERS THEN
        presult := 0;
    
END proc_m3;

 

- Java

Connection conn = null;
CallableStatement stat = null;

try {
	
	String sql = "{ call proc_m3(?,?,?,?,?) }";
	
	conn = DBUtil.open();
	stat = conn.prepareCall(sql);
	
	// in 매개변수 x 4개
	stat.setString(1, "고양이");
	stat.setString(2, "25");
	stat.setString(3, "f");
	stat.setString(4, "서울시 강남구 대치동");
	
	// out 매개변수 x 1개
	stat.registerOutParameter(5, OracleTypes.NUMBER); // ***********
	stat.executeUpdate();
	
	// 결과값
	String result = stat.getString(5);
	System.out.println("결과: " + result); // *****************
	
	stat.close();
	conn.close();
	
} catch (Exception e) {
	e.printStackTrace();
}

 

- 결과

in 매개변수 입력으로 데이터는 잘 들어 갔으며, Java Console 화면에도 프로시저의 아웃파라미터 presult의 결과값 1도 출력완료

 

[ CallableStatement 예제 4 - 프로시저의 아웃 파라미터 받기 ]

- SEQ를 in 매개변수로 받아와 나머지 정보를 Out 매개변수로 받아오기

- 프로시저(SQL)

CREATE OR REPLACE PROCEDURE proc_m4(
    pseq IN NUMBER,
    pname OUT VARCHAR2, 
    PAGE OUT NUMBER,
    pgender OUT VARCHAR2,
    paddress OUT VARCHAR2
)
IS
BEGIN

    SELECT 
        NAME, age, gender, address 
    INTO 
        pname, PAGE, pgender, paddress
    FROM tbladdress 
    WHERE seq = pseq;
    
END proc_m4;

 

- Java

Connection conn = null;
CallableStatement stat = null;

try {
	
    String sql = "{ call proc_m4(?,?,?,?,?) }";
	
	conn = DBUtil.open();
	stat = conn.prepareCall(sql);
	
	// in (값 넣기)
	stat.setString(1, "45");
	
	// out (등록하기)
	stat.registerOutParameter(2, OracleTypes.VARCHAR);
	stat.registerOutParameter(3, OracleTypes.NUMBER);
	stat.registerOutParameter(4, OracleTypes.VARCHAR);
	stat.registerOutParameter(5, OracleTypes.VARCHAR);
	
	// 실행하기
	stat.executeQuery();
	
	// 값 접근
	String name = stat.getString(2);
	int age = stat.getInt(3);
	String gender = stat.getString(4);
	String address = stat.getString(5);
	
	System.out.println(name);
	System.out.println(age);
	System.out.println(gender);
	System.out.println(address);
	
	stat.close();
	conn.close();
	
} catch (Exception e) {
	e.printStackTrace();
}

 

- 결과 ( tblAddress에 들어있는 데이터값 중 seq = 45를 검색 )

 

[ CallableStatement 예제 5 - 다중 레코드 반환하기(cursor 반환) ]

- gender(성별)을 in 매개변수로 받아와서 cursor 반환하기

- 프로시저(SQL)

CREATE OR REPLACE PROCEDURE PROC_M5(
    PGENDER IN VARCHAR2,
    PCURSOR OUT SYS_REFCURSOR
)
IS
BEGIN
    
    OPEN PCURSOR FOR
        SELECT * FROM TBLADDRESS WHERE GENDER = PGENDER;

END PROC_M5;

 

- Java

Connection conn = null;
CallableStatement stat = null;
ResultSet rs = null;

try {
	
	String sql = "{ call proc_m5(?,?) }";
	
	conn = DBUtil.open();
	stat = conn.prepareCall(sql);
	
	// in
	stat.setString(1, "m");
	
	// out
	stat.registerOutParameter(2, OracleTypes.CURSOR);
	
	// 실행
	stat.executeQuery();
	
	// 이게 포인트 **** 프로시저에서 반환할 커서는 자바에서 ResultSet으로 받는다.
	rs = (ResultSet)stat.getObject(2);
	
	while ( rs.next() ) {
		System.out.println(rs.getString("name") + ", " + rs.getString("gender"));
	}
	
	rs.close();
	stat.close();
	conn.close();
	
} catch (Exception e) {
	e.printStackTrace();
}

 

- 결과

남자('m') 데이터만 가져온 결과를 콘솔화면에 출력한 모습이다.

 

[ Statement 요약 ]

  Statement   정적 쿼리 실행
  PreparedStatement   동적 쿼리 실행
  CallableStatement   프로시저 실행. ( PreparedStatement 유사 )

MEMO>

# 비슷비슷한 문법, 따옴표 써야되는지 말아야되는지 등등 익숙치 않아서 오타가 자주 발생하는 것 같다. 주의.

# 교수님이 엄청 강조하신 수업이다 JDBC. ( 수업량은 적은데, 실무에서 쓰이는 정도가 어마어마하다. -> 가성비 최고!! )

# Statement도 써보고, PreparedStatement도 써보고, CallableStatement도 써보고 흐름을 기억하고 상황에 맞춰서 쓸 수 있게 하자.