JDBC

[JDBC]days05- CallableStatement , 자바에서 커서 이용

애플쩀 2022. 5. 11. 11:35
CallableStatement 

프로시저를 호출할 때 사용한다. 
Insert , update, delete 사용시 편리하다. 

자바에서 호출할때 
call 프로시저명 (매개변수)  

 

[오라클] 커서 - 자바에서 출력하고 닫도록 
create or replace procedure up_selectemp 
(
    pdeptno in dept.deptno%type
    ,pCursor out  SYS_REFCURSOR -- out : 결과물을 커서에 담아서 출력
)
is
 vsql varchar2(1000); 
begin
 vsql := 'SELECT deptno, empno, ename, job, hiredate ';
 vsql := vsql||' from emp ';
 vsql := vsql||' where deptno = :pdeptno';
 
 --동적쿼리 실행, 얘가 실행되면 결과물이 커서에 담긴다
 open pCursor for vsql --동적쿼리를 쓸때는 open for문 쓰는 것 기억
        using pdeptno;

end;

 

자바
  • 프로시저를 호출call, 매개변수는 두개(커서,부서번호) 
    String sql="{call UP_SELECTEMP(?,?)}";
  • 출력용매개변수이면서 커서타입을 받겠다. 
    cstmt.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR);
  • 커서에 결과물이 담겨져 있기 때문에 resultSet으로 변환하고  반환한다 .
    rs=(ResultSet)cstmt.getObject(2);
package days06;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

import com.util.DBconn;

import days02.EmpDTO;

public class Prac {

	public static void main(String[] args) {

		//UP_SELECTEMP;
		System.out.print("> deptno input ? ");
		Scanner scanner = new Scanner(System.in);
		int  deptno = scanner.nextInt();
				//원래 int인데 String으로 날려도 전혀 상관 없음
				//오라클은 홑따옴표를 사용하기 때문 
		
		Connection con = null;
		CallableStatement cstmt= null;
		ResultSet rs= null;
		ArrayList<EmpDTO> list = null;
		
		String sql ="{ call UP_SELECTEMP( ? ,? ) }";
		
		con = DBconn.getConnection();
		try {
			cstmt = con.prepareCall(sql);
			// ? 
			cstmt.setInt(1, deptno);
			// ? OUT 출력용 매개변수 설정
			cstmt.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR);
			
			// rs= cstmt.executeQuery(); 이게 아니라 두번째 파라미터 값인 커서로 돌려준다
			 cstmt.executeQuery();
			 rs = (ResultSet) cstmt.getObject(2); //다운캐스팅 작업 
			 
			 if(rs.next()) {
				 list= new ArrayList<EmpDTO>();
				 EmpDTO dto = null;
				 do {
					 dto = new EmpDTO( );
					 dto.setEmpno(rs.getInt("empno"));
					 dto.setDeptno(deptno);
					 dto.setEname(rs.getString("ename"));
                  			   dto.setJob(rs.getString("job"));
					 dto.setHiredate(rs.getDate("hiredate"));
					 
					 list.add(dto);
				 }while(rs.next());
			 }//if
			 
			 
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				rs.close();
				cstmt.close();
				DBconn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}//finally
		
		printEmpInfo(list);
				
	}//main

	private static void printEmpInfo(ArrayList<EmpDTO> list) {
		if(list == null) {
			System.out.println("사원이 존재하지 않습니다");
		}else {
			Iterator<EmpDTO> ir = list.iterator();
			while (ir.hasNext()) {
				EmpDTO dto =  ir.next();
				System.out.println(dto);	
			}
		}
		
	}}

 

오라클  아이디 중복 체크 

 

create or replace procedure up_logon2
(
    pempno in number             --id     in
    ,  pename in varchar2          --pwd    in
    ,  plogoncheck out number   -- 1,2,0    out
)
is
   vempno number(1) ;   --  0    1(아이디존재)
   vename emp.ename%type;
begin
   select count(*) into vempno
   from emp
   where empno = pempno;
   if  vempno = 0 then
        plogoncheck := 1; --아이디가 존재하지 않는 경우 (아이디 사용 가능)
   else
      select ename into vename
      from emp
      where empno = pempno;      
      if pename = vename then
         plogoncheck := 0; -- 로그인 성공
      else
         plogoncheck := 2; --비밀번호가 틀린 경우
      end if;      
   end if;
--exception
end;
자바 

나중에 Query+Ajax에서 처리 

package days06;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

import com.util.DBconn;

import days02.EmpDTO;

public class Prac {

	public static void main(String[] args) {

	package days06;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

import com.util.DBconn;

import days02.EmpDTO;

public class Prac {

	public static void main(String[] args) {
		System.out.println("중복체크할 id ,passwd 입력 ");
		Scanner sc=new Scanner(System.in);
		int empno=sc.nextInt();
		String ename=sc.next();
			
		Connection conn=null;
		CallableStatement cstmt=null;
		
		
		String sql="call up_logon2(?,?,?)";
		conn=DBconn.getConnection();
		
		int logonCheck=0;
		
		try {
			cstmt=conn.prepareCall(sql);
			cstmt.setInt(1,empno);
			cstmt.setString(2, ename);
			//출력용파마리터 
			cstmt.registerOutParameter(3, oracle.jdbc.OracleTypes.INTEGER);
			cstmt.executeQuery();
			logonCheck=(int)cstmt.getObject(3);
			if(logonCheck==1) {
				System.out.println("아이디존재 x");
			}else if(logonCheck==0) {
				System.out.println("로그인성공");
			}else if (logonCheck==2) {
				System.out.println("비밀번호잘못");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				cstmt.close();
				DBconn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
		
	}}



	

	
		
	}}

처음에 제대로 출력결과가 나오지 않았다. 

이유 => logonCheck=(int)cstmt.getObject(3);

이부분을 빠트려서 출력용 logonCheck 를 받아오지 않았던것 

 

 

소문자로 smith 라고 하면 안된다!

중요

cstmt.registerOutParameter(3, oracle.jdbc.OracleTypes.INTEGER);
cstmt.executeQuery();
logonCheck=(int)cstmt.getObject(3);