자바 호출 저장 프로시저

11506 단어 Java직장레저
요약:
본 고 는 DBMS 저장 과정 을 어떻게 사용 하 는 지 논술 하 였 다.나 는 ResultSet 로 돌아 가 는 등 저장 프로 세 스 를 사용 하 는 기본 적 이 고 고급 특성 을 논술 했다.본 고 는 DBMS 와 JDBC 에 대해 잘 알 고 있다 고 가정 하고 다른 언어 로 작 성 된 코드(즉 자바 의 언어 가 아 닌 것)를 장애 없 이 읽 을 수 있다 고 가정 하지만 저장 과정의 프로 그래 밍 경험 을 요구 하지 않 는 다.
본 고 는 DBMS 저장 과정 을 어떻게 사용 하 는 지 논술 하 였 다.나 는 ResultSet 로 돌아 가 는 등 저장 프로 세 스 를 사용 하 는 기본 적 이 고 고급 특성 을 논술 했다.본 고 는 DBMS 와 JDBC 에 대해 잘 알 고 있다 고 가정 하고 다른 언어 로 작 성 된 코드(즉 자바 의 언어 가 아 닌 것)를 장애 없 이 읽 을 수 있다 고 가정 하지만 저장 과정의 프로 그래 밍 경험 을 요구 하지 않 는 다.저장 프로 세 스 는 데이터베이스 에 저장 하고 데이터베이스 에서 실행 하 는 프로그램 을 말한다.너 는 특수 한 문법 을 사용 하여 자바 류 에서 저장 과정 을 호출 할 수 있다.호출 시 저장 프로 세 스 의 이름과 지 정 된 매개 변 수 는 JDBC 연결 을 통 해 DBMS 에 전송 되 며 저장 프로 세 스 를 실행 하고 연결 을 통 해 결 과 를 되 돌려 줍 니 다.저장 프로 세 스 를 사용 하 는 것 은 EJB 나 CORBA 기반 애플 리 케 이 션 서버 를 사용 하 는 것 과 같은 장점 이 있 습 니 다.저장 프로 세 스 는 많은 유행 하 는 DBMS 에서 무료 로 사용 할 수 있 지만 애플 리 케 이 션 서버 는 대부분 비싸다.이것 은 허가증 비용 의 문제 만 은 아니다.응용 서버 를 사용 하 는 데 필요 한 관리,코드 작성 비용,그리고 클 라 이언 트 프로그램 이 증가 하 는 복잡성 은 모두 DBMS 의 저장 과정 을 통 해 전체 적 으로 대체 할 수 있 습 니 다.자바,Python,Perl 또는 C 를 사용 하여 저장 과정 을 작성 할 수 있 지만,일반적으로 DBMS 가 지정 한 특정 언어 를 사용 합 니 다.Oracle 은 PL/SQL,PostgreSQL 은 pl/pgsql,DB2 는 Procedural SQL 을 사용한다.이 언어 들 은 모두 매우 비슷 하 다.이들 사이 에 저장 과정 을 이식 하 는 것 은 Sun 의 EJB 규범 에 따라 버 전 간 에 Session Bean 을 이식 하 는 것 보다 어렵 지 않다.또한 저장 과정 은 SQL 을 삽입 하기 위해 설계 되 었 기 때문에 자바 나 C 등 언어 보다 데이터 베 이 스 를 더욱 우호 적 으로 표현 하 는 메커니즘 이다.메모리 프로 세 스 가 DBMS 자체 에서 실행 되 기 때문에 응용 프로그램의 대기 시간 을 줄 이 는 데 도움 이 되 기 때문이다.자바 코드 에서 4 개 또는 5 개의 SQL 문 구 를 실행 하 는 것 이 아니 라 서버 에서 1 개의 저장 과정 만 실행 해 야 합 니 다.인터넷 상의 데이터 왕복 횟수 의 감 소 는 극 적 으로 성능 을 최적화 할 수 있다.저장 프로 세 스 가 간단 한 오래된 JDBC 를 사용 하여 Callable Statement 류 를 통 해 저장 프로 세 스 호출 을 지원 합 니 다.이 종 류 는 실제로 Prepared Statement 의 하위 클래스 입 니 다.만약 에 우리 가 poets 데이터 베 이 스 를 가지 고 있다 고 가정 하면데이터베이스 에는 시인 의 사망 연령 을 설정 하 는 저장 과정 이 있다.다음은 술고래 딜 런 토 마 스(old soak Dylan Thomas)에 대해 전고,문화 에 관 한 지 여 부 를 지정 하지 않 고 비판 하고 지적 해 주세요.번역 주석)호출 된 상세 코드:
try{ 
int age = 39;

String poetName = "dylan thomas";

CallableStatement proc = connection.prepareCall("{ call set_death_age(?, ?) }");

proc.setString(1, poetName);

proc.setInt(2, age);

cs.execute();

}catch (SQLException e){ // ....}

prepareCall 방법 에 전 달 된 문자열 은 저장 과정 에서 호출 된 쓰기 규범 입 니 다.저장 프로시저 의 이름 을 지 정 했 습 니 다.?지정 한 인자 가 필요 합 니 다.JDBC 와 통합 하 는 것 은 저장 과정의 큰 편리 함 입 니 다.응용 프로그램 에서 저장 과정 을 호출 하기 위해 서 는 루트(stub)류 나 프로필 이 필요 하지 않 습 니 다.DBMS 의 JDBC 드라이버 외 에는 아무것도 필요 하지 않 습 니 다.이 코드 가 실 행 될 때 데이터베이스 의 저장 과정 이 호출 됩 니 다.우 리 는 그 저장 과정 이 결 과 를 되 돌려 주지 않 기 때문에 결 과 를 얻 지 못 했다.실행 성공 이나 실 패 는 예 외 를 통 해 알 게 될 것 이다.실 패 는 저장 과정 을 호출 하 는 데 실 패 했 거나(예 를 들 어 제 공 된 매개 변수의 유형 이 정확 하지 않 음)응용 프로그램의 실 패 를 의미 할 수 있 습 니 다.(예 를 들 어 하나의 예외 지 시 를 던 져 서 poets 데이터베이스 에'Dylan Thomas'가 존재 하지 않 음)SQL 작업 과 저장 과정 을 결합 하여 자바 대상 을 SQL 표 에 표시 하 는 줄 은 상당히 간단 하지만 보통 몇 개의 SQL 문 구 를 실행 해 야 합 니 다.SELECT 에서 ID 를 찾 은 다음 INSERT 에서 지정 한 ID 의 데 이 터 를 삽입 할 수 있 습 니 다.고도 규격 화(더 높 은 범례,번역 주 에 부합)된 데이터 베이스 모델 에 서 는 여러 표 의 업데이트 가 필요 할 수 있 으 므 로 더 많은 문구 가 필요 하 다.자바 코드 는 빠르게 팽창 하고 모든 문장의 네트워크 비용 도 빠르게 증가 할 것 이다.이 SQL 문 구 를 하나의 저장 과정 으로 옮 기 면 코드 를 크게 간소화 하고 한 번 의 네트워크 호출 에 만 관련 될 것 이다.모든 연 결 된 SQL 작업 은 데이터베이스 내부 에서 발생 할 수 있 습 니 다.또한,PL/SQL 과 같은 저장 프로 세 스 언어 는 자바 코드 보다 SQL 문법 을 사용 할 수 있 도록 해 줍 니 다.다음은 우리 의 초기 저장 과정 입 니 다.Oracle 의 PL/SQL 언어 로 작성 합 니 다.
create procedure set_death_age(poet VARCHAR2, poet_age NUMBER) 

poet_id NUMBER;

begin SELECT id INTO poet_id FROM poets WHERE name = poet;

INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age);

end set_death_age;

독특 하 다 고요?아니요.나 는 네가 반드시 poets 표 의 UPDATE 를 보 기 를 기대 할 것 이 라 고 내 기 를 걸 었 다.메모리 프로 세 스 를 이용 해 실현 하 는 것 이 얼마나 쉬 운 일 인지 암시 한다.set_death_age 는 거의 나 쁜 실현 이 라 고 확신 할 수 있다.우 리 는 죽은 나 이 를 저장 하기 위해 poets 표 에 열 을 추가 해 야 한다.자바 코드 에 서 는 데이터베이스 모델 이 어떻게 실현 되 는 지 에 관심 이 없다.왜냐하면 그것 은 저장 과정 만 호출 하기 때문이다.우 리 는 이후 에 데이터베이스 모델 을 바 꾸 어 성능 을 향상 시 킬 수 있 지만,우 리 는 우리 코드 를 수정 할 필요 가 없다.다음은 위 에 저 장 된 프로 세 스 를 호출 하 는 자바 코드 입 니 다.
public static void setDeathAge(Poet dyingBard, int age) throws SQLException{ 

Connection con = null;

CallableStatement proc = null;

try {

con = connectionPool.getConnection();

proc = con.prepareCall("{ call set_death_age(?, ?) }");

proc.setString(1, dyingBard.getName());

proc.setInt(2, age);

proc.execute();

}

finally {

try { proc.close(); }

catch (SQLException e) {}

con.close();

}

}

유지 가능성 을 확보 하기 위해 서 는?옷자락 이 기구 하 다.선반tatic 방법.이것 또한 저장 프로 세 스 를 호출 하 는 코드 를 간단 한 모드 코드 에 집중 시 켰 다.많은 저장 과정 을 사용 하면 복사,붙 여 넣 기만 하면 새로운 방법 을 만 들 수 있다 는 것 을 알 게 될 것 이다.코드 의 모드 화 때문에 스 크 립 트 를 통 해 저장 프로 세 스 를 호출 하 는 코드 를 자동 으로 생산 할 수도 있 습 니 다.Functions 저장 과정 에 반환 값 이 있 기 때문에 Callable Statement 류 는 getResultSet 과 같은 방법 으로 반환 값 을 가 져 옵 니 다.저장 프로 세 스 가 값 을 되 돌려 줄 때,JDBC 드라이브 의 SQL 형식 이 무엇 인지 registerOutParameter 방법 으로 알려 야 합 니 다.너 도 이 과정 이 값 을 되 돌려 주 는 것 을 지시 하기 위해 저장 프로 세 스 호출 을 조정 해 야 한다.다음은 위의 예 를 잇 겠 습 니 다.이번에 우 리 는 딜 런 토 마 스 가 세상 을 떠 났 을 때의 나 이 를 조회 했다.이번 저장 프로 세 스 는 PostgreSQL 의 pl/pgsql 을 사용 합 니 다.
create function snuffed_it_when (VARCHAR) returns integer 'declare 

poet_id NUMBER;

poet_age NUMBER;

begin

--first get the id associated with the poet.

SELECT id INTO poet_id FROM poets WHERE name = $1;

--get and return the age.

SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;

return age;

end;' language 'pl/pgsql';

또한,pl/pgsql 매개 변수 이름 은 유 닉 스 와 DOS 스 크 립 트 의$n 문법 으로 참조 되 어 있 습 니 다.또한,끼 워 넣 은 주석 도 주의 하 세 요.이것 은 자바 코드 에 비해 또 다른 우수 성 입 니 다.자바 에 이런 주석 을 쓰 는 것 은 물론 가능 하지만 어 지 럽 고 SQL 구문 과 어 긋 나 므 로 자바 String 에 삽입 해 야 합 니 다.다음은 이 저장 프로 세 스 를 호출 하 는 자바 코드 입 니 다.
connection.setAutoCommit(false); 

CallableStatement proc = connection.prepareCall("{ ? = call snuffed_it_when(?) }");

proc.registerOutParameter(1, Types.INTEGER);

proc.setString(2, poetName);

cs.execute();

int age = proc.getInt(2);

잘못된 반환 값 형식 을 지정 하면 어떻게 됩 니까?그러면 저장 과정 을 호출 할 때 Runtime Exception 을 던 집 니 다.ResultSet 작업 에서 잘못된 형식 을 사용 한 것 처럼.복잡 한 반환 값 은 저장 과정 에 관 한 지식 으로 많은 사람들 이 우리 가 토론 한 것 에 익숙 한 것 같다.이것 이 저장 과정의 모든 기능 이 라면 저장 과정 은 다른 원 격 실행 체제 의 교체 방안 이 아니다.저장 과정의 기능 은 이것 보다 훨씬 강하 다.SQL 조 회 를 실행 할 때 DBMS 는 cursor(커서)라 는 데이터베이스 대상 을 만 들 고 결 과 를 되 돌려 주 는 데 사용 합 니 다.ResultSet 은 현재 시점 의 커서 의 표시 입 니 다.캐 시 나 특정 데이터 베 이 스 를 지원 하지 않 고 ResultSet 에서 만 앞으로 이동 할 수 있 는 이유 입 니 다.일부 DBMS 는 저장 과정 에서 커서 의 인용 을 되 돌려 줍 니 다.JDBC 는 이 기능 을 지원 하지 않 지만 Oracle,PostgreSQL,DB2 의 JDBC 드라이브 는 ResultSet 에서 커서 로 열 리 는 포인터(pointer)를 지원 합 니 다.정년 까지 살 았 는 지 아 닌 지 를 보 여 주 는 시인 을 구상 합 니 다.다음은 이 기능 을 완성 하 는 저장 과정 입 니 다.열 린 커서 를 되 돌려 주 고 PostgreSQL 의 pl/pgsql 언어 도 사용 합 니 다.
create procedure list_early_deaths () return refcursor as 'declare 

toesup refcursor;

begin

open toesup for SELECT poets.name, deaths.age FROM poets, deaths
-- all entries in deaths are for poets. -- but the table might become generic. 

WHERE poets.id = deaths.mort_id AND deaths.age < 60;

return toesup;

end;' language 'plpgsql';

다음은 이 저장 프로 세 스 의 자바 방법 을 호출 하여 결 과 를 PrintWriter 에 출력 합 니 다.
PrintWriter: 

static void sendEarlyDeaths(PrintWriter out){

Connection con = null;

CallableStatement toesUp = null;

try {

con = ConnectionPool.getConnection();

// PostgreSQL needs a transaction to do this... con.

setAutoCommit(false); // Setup the call.

CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");

toesUp.registerOutParameter(1, Types.OTHER);

toesUp.execute();

ResultSet rs = (ResultSet) toesUp.getObject(1);

while (rs.next()) {

String name = rs.getString(1);

int age = rs.getInt(2);

out.println(name + " was " + age + " years old.");

}

rs.close();

}

catch (SQLException e) { // We should protect these calls. toesUp.close(); con.close();

}

}

JDBC 는 저장 과정 에서 커서 를 되 돌려 주 는 것 을 직접 지원 하지 않 기 때문에 저 희 는 Types.OTHER 를 사용 하여 저장 과정의 반환 유형 을 표시 한 다음 getObject()방법 을 호출 하여 반환 값 을 강제 형식 으로 변환 합 니 다.이 저장 프로 세 스 를 호출 하 는 자바 방법 은 mapping 의 좋 은 예 입 니 다.Mapping 은 한 집의 조작 에 대해 추상 적 인 방법 이다.이 과정 에서 집합 을 되 돌려 주 는 것 이 아니 라,우 리 는 조작 을 전송 해서 실행 할 수 있다.이 예 에서,동작 은 ResultSet 를 출력 흐름 에 인쇄 하 는 것 입 니 다.이것 은 예 를 들 어 자주 사용 할 수 있 는 예 입 니 다.다음은 같은 저장 과정 을 호출 하 는 또 다른 방법 으로 이 루어 집 니 다.
public class ProcessPoetDeaths{ 

public abstract void sendDeath(String name, int age);

}

static void mapEarlyDeaths(ProcessPoetDeaths mapper){

Connection con = null;

CallableStatement toesUp = null;

try {

con = ConnectionPool.getConnection();

con.setAutoCommit(false);

CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");

toesUp.registerOutParameter(1, Types.OTHER);

toesUp.execute();

ResultSet rs = (ResultSet) toesUp.getObject(1);

while (rs.next()) {

String name = rs.getString(1);

int age = rs.getInt(2);

mapper.sendDeath(name, age);

}

rs.close();

} catch (SQLException e) { // We should protect these calls. toesUp.close();

con.close();

}

}

ResultSet 데이터 에서 임의의 처 리 를 수행 할 수 있 습 니 다.ResultSet 를 가 져 오 는 방법 을 변경 하거나 복사 하지 않 아 도 됩 니 다.
static void sendEarlyDeaths(final PrintWriter out){ 

ProcessPoetDeaths myMapper = new ProcessPoetDeaths() {

public void sendDeath(String name, int age) {

out.println(name + " was " + age + " years old.");

}

};

mapEarlyDeaths(myMapper);

}

이 방법 은 ProcessPoetDeaths 의 익명 인 스 턴 스 를 사용 하여 mapEarly Deaths 를 호출 합 니 다.이 인 스 턴 스 는 sendDeath 방법의 실현 을 가지 고 있 으 며,위의 예 와 같은 방식 으로 결 과 를 출력 흐름 에 기록 합 니 다.물론 이 기술 은 저장 과정 특유 의 것 이 아니 지만 저장 과정 에서 돌아 오 는 ResultSet 와 결합 하여 사용 하 는 매우 강력 한 도구 이다.결론 저장 과정 은 코드 에서 논 리 를 분리 하 는 데 도움 을 줄 수 있다.이것 은 기본적으로 항상 유익 하 다.이 분리 의 장점 은?6?1.응용 프로그램 을 신속하게 만 들 고 응용 과 함께 변경 하고 개선 하 는 데이터 베이스 모델 을 사용 합 니까?6?1.데이터베이스 모델 은 나중에 자바 대상 에 영향 을 주지 않 고 바 꿀 수 있 습 니 다.우리 가 응용 을 완성 하면 더 좋 은 모델 을 다시 설계 할 수 있 습 니까?6?1.저장 과정 은 더 좋 은 SQL 삽입 을 통 해 복잡 한 SQL 을 쉽게 이해 할 수 있 습 니 다.?6?1.자바 에 삽 입 된 SQL 을 작성 하 는 것 보다 저장 과정 을 작성 하 는 것 이 더 좋 은 도 구 를 가지 고 있 습 니 다.-대부분의 편집기 에서 문법 하 이 라 이 트 를 제공 합 니 다!?6?1.저장 과정 은 모든 SQL 명령 행 에서 테스트 할 수 있 기 때문에 디 버 깅 이 더욱 쉽다.모든 데이터 베 이 스 는 저장 과정 을 지원 하 는 것 은 아니 지만 무료/오픈 소스 와 비 무료 등 좋 은 실현 이 많이 존재 하기 때문에 이식 은 문제 가 되 지 않 습 니 다.Oracle,PostgreSQL,DB2 는 모두 비슷 한 저장 프로 세 스 언어 를 가지 고 있 으 며 온라인 커 뮤 니 티 가 잘 지원 하고 있다.저장 프로 세 스 도구 가 많 습 니 다.TOAD 나 TORA 와 같은 편집기,디 버 거,IDE 가 있 습 니 다.PL/SQL 또는 pl/pgsql 을 작성 하고 유지 하 는 강력 한 환경 을 제공 합 니 다.저장 과정 은 확실히 당신 의 코드 비용 을 증가 시 켰 지만,대부분의 응용 서버 에 비해 비용 이 훨씬 적다.

좋은 웹페이지 즐겨찾기