02.Oracle/DataBase2008. 11. 17. 14:35
반응형

ora-00000     성공적인 정상 종료입니다.
ora-00001     유일성 제약조건(%s.%s)에 위배됩니다.
ora-00017     트레이스 이벤트 설정이 세션에 요구되었습니다.
ora-00018     최대 세션 수를 초과했습니다.
ora-00019     최대 세션 라이선스 수를 초과했습니다.
ora-00020     최대 프로세스 수(%s)를 초과했습니다.
ora-00021     세션이 다른 프로세스에 첨부되어 있음; 세션을 변경할 수 없습니다.
ora-00022     부적절한 세션 번호; 액세스가 거절되었습니다.
ora-00023     세션이 프로세스 고유의 메모리를 참조함; 세션을 분리할 수 없습니다.
ora-00024     단일 프로세스 모드에서는 하나 이상의 프로세스가 로그인할 수 없습니다.
ora-00025     %s에 메모리를 할당하는데 실패했습니다.
ora-00026     누락 혹은 부적합한 세션 번호
ora-00027     현 세션을 제거할 수 없습니다.
ora-00028     세션이 제거되었습니다.
ora-00029     사용자 세션이 아닙니다.
ora-00030     사용자 세션 id가 존재하지 않습니다.
ora-00031     세션이 중단될 것입니다.
ora-00032     부적합한 세션 migration password
ora-00033     현세션이 migration password를 갖고있지 않습니다.
ora-00034     pl/sql 세션에서 %s를 할 수 없습니다.
ora-00035     license_max_users가 현재의 사용자 수보다 적을 수 없습니다.
ora-00050     엔큐를 하는 동안 o/s 오류가 발생했음. o/s 오류를 확인하십시오
ora-00051     자원 대기 중 시간 초과입니다.
ora-00052     최대 엔큐 자원 수(%s)를 초과했습니다.
ora-00053     최대 엔큐 수를 초과했습니다.
ora-00054     자원이 사용중이고, nowait가 지정되어 있습니다.
ora-00055     최대 dml 잠금 수를 초과했습니다.
ora-00056     개체 %s.%s에 대한 ddl 잠금이 비호환 모드로 되어 있습니다.
ora-00057     최대 임시 테이블 잠금 수가 초과했습니다.
ora-00058     이 데이타베이스를 마운트하기 위해서 db_block_size가 %s이어야 함(%s 아님).
ora-00059     최대 db_files 수를 초과했습니다.
ora-00060     자원 대기중 데드록이 검출되었습니다.
ora-00061     다른 하나의 인스턴스가 다른 dml_locks을 설정하고 있습니다.
ora-00062     dml 전(full) 테이블 잠금을 취할 수 없습니다. dml_locks은 0 입니다.
ora-00063     최대 log_files 수를 초과했습니다.
ora-00064     현 o/s (%s,%s)에 할당하기에는 개체가 너무 큽니다.
ora-00065     fixed_date의 초기화에 실패했습니다.
ora-00066     log_files는 %s이지만 호환성을 위해 %s 이어야합니다.
ora-00067     값 %s은 파라미터 %s에 대해 부적당하며, 최소한 %s 이어야 합니다.
ora-00068     값 %s은 파라미터 %s에 대해 부적당하며, %s와 %s 사이의 값이어야 합니다.
ora-00069     잠글 수 없습니다 -- %s에 대해 테이블 잠금을 할 수 없습니다.
ora-00070     명령어 %s 은 적당하지 않습니다.
ora-00071     프로세스 번호은 1 과 %s 사이어야 합니다.
ora-00072     프로세스 %s 은 활동적인 것이 아닙니다.
ora-00073     명령어 %s은 %s 와 %s 인수를 가지고 옵니다.
ora-00074     지정된 프로세스가 없습니다.
ora-00075     프로세스 %s 은 이 인스턴스에서 찾을 수 없습니다.
ora-00076     덤프 %s 을 찾을 수 없습니다.
ora-00077     덤프 %s 은 적당하지 않습니다.
ora-00078     이 이름으로 변수를 덤프 할 수 없습니다.
ora-00079     변수 %s 가 없습니다.
ora-00080     레벨 %s 로 지정된 글로벌 영역이 부적당합니다.
ora-00081     주소 범위 [%s, %s)은 읽기가능한 것이 아닙니다.
ora-00082     %s의 메모리 크기는 적당한 [1], [2], [4]%s%s%s%s%s의 설정으로 되어 있지 않습니다.
ora-00083     경고: 맵된 sga가 손상한것 같습니다.
ora-00084     글로벌 영역이 pga, sga, 또는 uga 이어야만 합니다.
ora-00085     현재 호출이 존재하지 않습니다.
ora-00086     사용자 호출이 존재하지 않습니다.
ora-00097     oracle sql 기능에서 사용하고 있는것이 sql92 %s 레벨서 존재하고 있지 않습니다.
ora-00100     데이터가 없습니다.
ora-00101     시스템 파라미터 mts_dispatchers에 대한 사용 문법이 부적합합니다.
ora-00102     %s 네트워크 프로토콜이 디스패쳐에 의해 사용될 수 없습니다.
ora-00103     부적합한 네트워크 프로토콜; 디스패쳐에 의해 사용되도록 예약되었음
ora-00104     데드록이 검출되었음; 모든 공유서버가 자원을 기다리고 있습니다.
ora-00105     디스패칭 기법이 %s 네트워크 프로토콜을 지원하도록 되어있지 않습니다.
ora-00106     디스패쳐에 연결되었을때는 데이타베이스를 기동/중지시킬 수 없습니다.
ora-00107     oracle의 리스너 프로세스에 연결하지 못했습니다.
ora-00108     비동기 연결이 가능하도록 디스패쳐를 설정하지 못했습니다.
ora-00111     최대 서버수는 %s입니다; %s개의 서버 추가중
ora-00112     경고: %s (지정 최대치) 디스패쳐만으로 생성되었습니다.
ora-00113     프로토콜명 %s가 너무 깁니다.
ora-00114     시스템 파라미터 mts_service에 대한 값이 없습니다.
ora-00115     연결이 거절됨; 디스패쳐 연결 레이블이 full 상태입니다.
ora-00116     mts_service명이 너무 깁니다.
ora-00117     시스템 파라미터 mts_servers의 범위를 벗어납니다.
ora-00118     시스템 파라미터 mts_dispatchers의 범위를 벗어납니다.
ora-00119     mts_listener_address 시스템 파라미터에 지정이 부적합합니다.
ora-00120     디스패칭 기법이 사용불가 혹은 설치되어있지 않습니다.
ora-00121     mts_dispatchers를 제외하고 mts_servers가 지정되었습니다.
ora-00122     네트워크 구성을 초기화할 수 없습니다.
ora-00123     비작업중인 공유 서버를 종료합니다.
ora-00124     mts_dispatchers가 mts_max_servers 없이 지정되었습니다.
ora-00150     중복된 트랜잭션 id
ora-00151     부적합한 트랜잭션 id
ora-00152     현 세션이 요구된 세션과 일치하지 않습니다.
ora-00200     제어 화일 %s을 생성할 수 없습니다.
ora-00201     제어 화일 버전 %s은 oracle 버전 %s과 호환되지 않습니다.
ora-00202     제어화일: %s
ora-00203     잘못된 제어화일을 사용하였습니다.
ora-00204     제어 화일 %s (블록 %s, 블록 수 %s) 읽기 오류입니다.
ora-00205     제어 화일 %s 식별 오류입니다.
ora-00206     제어 화일 %s (블록 %s, 블록 수 %s) 쓰기 오류입니다.
ora-00207     제어화일이 현재 사용중인 데이타베이스용이 아닙니다.
ora-00208     제어 화일명이 최대수 %s 를 초과했습니다.
ora-00209     블록 크기 %s 가 최대 %s 바이트를 초과했습니다.
ora-00210     제어 화일 %s 를 열 수 없습니다.
ora-00211     제어 화일 %s 가 앞의 제어 화일과 일치하지 않습니다.
ora-00212     블록 크기 %s가 최소한 필요한 크기 %s 바이트 미만입니다.
ora-00213     제어 화일 %s 재사용 불가; 구 화일 크기 %s, %s가 필요합니다.
ora-00214     제어 화일 %s의 버전 %s는 화일 %s 버전 %s와 일치하지 않습니다.
ora-00215     적어도 한 개의 제어 화일이 필요합니다.
ora-00216     제어 화일 %s 에 대한 물리 블록 크기를 확정할 수 없습니다.
ora-00217     제어 화일 %s의 물리적 블록 크기 %s가 %s와 일치하지 않습니다.
ora-00218     제어 화일 %s는 블록 크기를 %s로 작성되었지만 현재는 %s 입니다.
ora-00219     필요한 제어 화일 크기 %s 가 최대치 %s 보다 큽니다.
ora-00220     제어화일 %s가 첫 인스턴스에 의해 사용한 것과 일치하지 않습니다.
ora-00221     제어화일에의 쓰기오류
ora-00222     디스패쳐로 제어화일을 조회할 수 없습니다.
ora-00223     변환 데이타화일이 부적합하거나 틀린 버전입니다.
ora-00224     명시된 화일이 제어 화일이 아닙니다.
ora-00225     기대된 크기 %s 은( 제어화일 %s 관한) 실제 크기 %s 와 다릅니다.
ora-00250     아카이버가 작동되지 않았습니다.
ora-00251     사용되지 않는 오류
ora-00252     로그 %s (쓰레드 %s의)는 비었습니다. 아카이브할 수 없습니다.
ora-00253     제한치 %s가 길이 %s로 초과되었습니다 (아카이브 스트링 %s의)
ora-00254     아카이브 제어 스트링 %s 오류입니다.
ora-00255     로그 %s(쓰레드 %s, 시퀀스 번호 %s)의 아카이브 오류
ora-00256     아카이브 텍스트 스트링 %s의 변환시 오류가 발생했습니다.
ora-00257     아카이버 오류. 해제되기 전에는 내부 연결만 가능
ora-00258     noarchivelog 모드에서의 수동 아카이브는 로그를 지정해야합니다.
ora-00259     로그 %s(개방 쓰레드 %s의)가 현재 로그이므로 아카이브할 수 없습니다.
ora-00260     온라인 로그 시퀀스 %s(쓰레드 %s의)를 발견할 수 없습니다.
ora-00261     로그 %s(쓰레드 %s의)가 아카이브중이거나 수정중입니다.
ora-00262     현재 로그 %s(닫힌 쓰레드 %s의)를 스위치할 수 없습니다.
ora-00263     쓰레드 %s를 위해 아카이빙이 필요한 로그가 없습니다.
ora-00264     복구가 필요하지 않습니다.
ora-00265     인스턴스 복구가 요구됩니다. archivelog모드를 지정할 수 없습니다.
ora-00266     아카이브된 로그 화일의 이름을 필요로 합니다.
ora-00267     아카이브된 로그 화일의 이름을 필요로 하지 않습니다.
ora-00268     지정된 로그화일이 존재하지 않습니다 %s
ora-00269     지정된 로그화일은 쓰레드 %s의 (%s가 아닌) 부분임
ora-00270     아카이브 로그 생성시 오류
ora-00271     아카이브를 필요로 하는 로그가 없습니다.
ora-00272     아카이브 로그 기록시 오류
ora-00273     로그되지 않은 직접 로드 데이타의 매체 복구
ora-00274     부적절한 복구 옵션 %s
ora-00275     매체 복구가 이미 시작되었습니다.
ora-00276     키워드 change가 지정되었으나 변환 번호가 주어지지 않았습니다.
ora-00277     until 복구 플래그 %s에 부적절한 옵션
ora-00278     현 복구를 위해 로그화일 %s는 더이상 필요하지 않습니다.
ora-00279     변환 %s가 (%s에서 생성된) 쓰레드 %s에 필요합니다.
ora-00280     변환 %s(쓰레드 %s를 위한)가 시퀀스번호 %s에 있습니다.
ora-00281     매체 복구는 디스패쳐를 사용하여 수행되지 않습니다.
ora-00282     upi %s 호출이 지원되지 않으니, alter database recover를 사용하십시요
ora-00283     복구 세션이 오류로 인하여 취소되었습니다.
ora-00284     복구 세션이 진행중입니다.
ora-00285     time 키워드가 지정되었으나 시간이 주어지지 않았습니다.
ora-00286     이용가능한 멤버가 없거나, 적합한 데이타를 포함하고 있지 않습니다.
ora-00287     지정된 변환 번호 %s가 쓰레드 %s에 없습니다.
ora-00288     복구를 계속하려면 alter database recover continue를 입력하십시요
ora-00289     제안 : %s
ora-00290     로그화일을 아카이브 하려고 할때, o/s 오류가 발생했습니다.
ora-00291     parallel 옵션에 숫자값이 필요로합니다.
ora-00292     병렬 복구 기능이 설치되지 않았습니다.
ora-00293     제어 화일과 리두로그가 동기화 상태에서 벗어나 있습니다.
ora-00300     부적합한 리두 로그 블록 크기 %s가 지정됨 - 한계 %s 초과
ora-00301     로그 화일 %s를 추가 작성할 수 없습니다.
ora-00302     로그의 최대수 %s 를 초과했습니다.
ora-00304     요구된 인스턴스 번호는 사용중입니다.
ora-00305     로그 %s(쓰레드 %s의)는 일관되지 않습니다. 이것은 다른 데이타베이스에 속합니다.
ora-00306     이 데이타베이스에서는 %s 인스턴스가 한계입니다.
ora-00307     요구된 인스턴스 번호가 범위를 벗어납니다(최대치는 %s)
ora-00308     아카이브된 로그 %s를 열 수 없습니다.
ora-00309     로그가 잘못된 데이타베이스에 속해 있습니다.
ora-00310     아카이브된 로그는 시퀀스 %s를 포함하고 있습니다 시퀀스 %s가 필요합니다.
ora-00311     아카이브 로그로부터 헤더 정보를 읽을 수 없습니다.
ora-00312     온라인 로그 %s 쓰레드 %s: %s
ora-00313     로그 그룹 %s (쓰레드 %s의)의 멤버를 여는데 실패했습니다.
ora-00314     로그 %s(쓰레드 %s의, 시퀀스번호가 %s일)는 %s와 일치하지 않습니다.
ora-00315     로그 %s (쓰레드 %s의) 헤더의 쓰레드 번호 %s가 틀립니다.
ora-00316     로그 %s (쓰레드 %s의) 헤더내의 유형 %s는 로그화일이 아닙니다.
ora-00317     헤더에 있는 화일형 %s가 로그화일이 아닙니다.
ora-00318     로그 %s (쓰레드 %s의, 화일 크기가 %s인)가 %s와 맞지 않습니다.
ora-00319     로그 %s(쓰레드 %s의)가 틀린 로그 재설정 상태를 가지고 있습니다.
ora-00320     로그 %s(쓰레드 %s의)로부터 화일 헤더를 읽을 수 없습니다.
ora-00321     로그 %s(쓰레드 %s의)에서 로그화일 헤더를 수정할 수 없습니다.
ora-00322     로그 %s(쓰레드 %s의)는 현시점의 것이 아닙니다.
ora-00323     쓰레드 %s의 현 로그는 사용불가하며, 나머지 전부도 아카이브하여야 합니다.
ora-00324     로그 화일 %s의 변환명 %s가 너무 깁니다, 문자수 %s가 %s를 초과했습니다.
ora-00325     쓰레드 %s으로 아카이브된 로그가 헤더내에 틀린 쓰레드 번호 %s를 가지고 있습니다.
ora-00326     변환 %s에서 시작된 아카이브 로그, 이전의 변환 %s를 필요로 합니다.
ora-00327     로그 %s(쓰레드 %s의), 물리적인 크기 %s가 필요한 %s보다 작습니다.
ora-00328     변환 %s에서 끝난 아카이브 로그, 이후의 변환 %s를 필요로 합니다.
ora-00329     변환 %s에서 시작된 아카이브 로그, 변환 %s를 필요로 합니다.
ora-00330     변환 %s에서 끝난 아카이브 로그, 변환 %s를 필요로 합니다.
ora-00331     로그 버전 %s가 oracle 버전 %s와 호환성이 없습니다.
ora-00332     아카이브된 로그가 너무 작음 - 완전하게 아카이브되지 않았습니다.
ora-00333     재실행 로그 읽기 오류(블록 %s 카운트 %s)
ora-00334     아카이브된 로그: %s
ora-00335     온라인 로그 %s: 이 번호의 로그가 존재하지 않습니다.
ora-00336     로그 화일의 크기 %s가 최소 블록 수 %s 보다 작습니다.
ora-00337     로그 화일 %s가 존재하지 않고 크기가 지정되어 있지 않습니다.
ora-00338     로그 %s(쓰레드 %s의)가 제어화일보다 최근의 것입니다.
ora-00339     아카이브 로그가 redo 로그를 포함하고 있지 않습니다.
ora-00340     온라인 로그 %s(쓰레드 %s의) 처리시 io 오류입니다.
ora-00341     로그 %s(쓰레드 %s의)에 대한 헤더내에 로그 번호 %s가 틀립니다.
ora-00342     아카이브된 로그가 마지막 resetlogs 전에 생성되었습니다.
ora-00343     너무 많은 오류 발생, 로그 멤버가 클로즈됐습니다.
ora-00344     온라인 로그 %s를 재생성할 수 없습니다.
ora-00345     redo 로그 쓰기(write) 오류, 블록 %s 카운트 %s
ora-00346     로그 멤버가 stale로 표시되었습니다.
ora-00347     로그 %s(쓰레드 %s의)의 예상 블록크기 %s는 %s와 일치하지 않습니다.
ora-00348     단일 프로세스 redo 실패입니다 인스턴스를 중지해야 합니다.
ora-00349     %s 의 블록 크기 확보 실패입니다.
ora-00350     로그 %s(쓰레드 %s의)를 아카이브해야 합니다.
ora-00351     지정된 시간으로의 복구가 불가능합니다.
ora-00352     쓰레드 %s에 대한 모든 로그가 아카이브되어야 함 - 가용화할 수 없습니다.
ora-00353     블록 %s 변경 %s 시간 %s 부근에서 로그가 깨졌습니다.
ora-00354     redo 로그의 블록헤더가 깨짐
ora-00355     변환 번호가 잘못됨
ora-00356     변환 설명내에 일치하지 않는 길이
ora-00357     로그화일에 너무 많은 수의 멤버가 지정됨 (최대치는 %s)
ora-00358     너무 많은 화일 멤버가 지정됨 (최대치는 %s)
ora-00359     로그화일 그룹 %s가 존재하지 않습니다.
ora-00360     로그화일 멤버가 아닙니다 %s
ora-00361     마지막 로그 멤버 %s는 그룹 %s를 옮길수 없습니다.
ora-00362     그룹 %s내에 정당한 로그화일을 형성하기 위해 멤버를 필요로 합니다.
ora-00363     로그가 아카이브 버전이 아닙니다.
ora-00364     새로운 로그 멤버에 헤더를 기록할 수 없습니다.
ora-00365     지정한 로그가 다음 로그가 아닙니다.
ora-00366     로그 %s, 쓰레드 %s의, 화일 헤더에 체크섬 오류가 있습니다.
ora-00367     로그 화일 헤더에 체크섬 오류가 있습니다.
ora-00368     리두 로그 블록에 체크섬 오류가 있습니다.
ora-00369     쓰레드 %s의 현재 로그는 사용불가이며 다른 로그가 지워지고 있습니다.
ora-00370     kcbchange 작업수행시 데드록의 가능성이 있습니다.
ora-00371     빈 버퍼의 사용이 불가합니다.
ora-00372     화일 %s는 지금 수정될 수 없습니다.
ora-00373     온라인 로그 버전 %s가 oracle 버전 %s와 호환되지 않습니다.
ora-00374     지정된 파라미터 db_block_size = %s 가 부적절함 - 가능한 범위[%s..%s]
ora-00375     디폴트 db_block_size의 값을 얻을수 없습니다.
ora-00376     현재 화일 %s를 읽을 수 없습니다.
ora-00390     로그 %s(쓰레드 %s의)는 지워질것이므로 현재 로그가 될 수 없습니다.
ora-00391     전체 쓰레드는 동시에 새로운 로그 포맷으로 전환해야 합니다.
ora-00392     로그 %s(쓰레드 %s의)는 지워질것이므로 작업이 허용되지 않습니다.
ora-00393     오프라인 데이타화일 복구에 로그 %s(쓰레드 %s의)가 필요합니다.
ora-00400     release 값 %s는 파라미터 %s에 부적절합니다.
ora-00401     이번 release에서 지원되지 않은 파라미터 %s에 대한 값입니다.
ora-00402     %s release에 변경된 데이타베이스는 %s release에 사용될 수 없습니다.
ora-00403     %s (%s) 는 다른 인스턴스(%s)와 같지 않습니다.
ora-00404     변환 데이타 화일이 없습니다 %s
ora-00405     호환 가능한 유형 %s
ora-00406     compatible 파라미터는 %s 이상이어야 합니다.
ora-00407     릴리즈 %s.%s 에서 %s.%s로 향상이 허용되지 않습니다.
ora-00408     파라미터 %s는 true로 설정되었습니다.
ora-00436     oracle이 라이센스되어 있지 않습니다 oracle사에 연락해 주십시오.
ora-00437     oracle의 기능이 라이센스되어 있지 않습니다. oracle사에 연락해 주십시오
ora-00443     백그라운 프로세스 %s가 시작되지 않았습니다.
ora-00444     백그라운드 프로세스 %s 기동중 장애가 발생했습니다.
ora-00445     백그라운드 프로세스 %s가 %s초 후 기동되지 않았습니다.
ora-00446     백그라운드 프로세스가 부적절하게 기동되었습니다.
ora-00447     백그라운드 프로세스에 치명적인 오류가 발생했습니다.
ora-00448     백그라운드 프로세스가 정상 종료했습니다.
ora-00449     백그라운드 프로세스 %s 가 오류 %s 와 함께 종료되었습니다.
ora-00470     lgwr 프로세스가 오류로 종료되었습니다.
ora-00471     dbwr 프로세스가 오류로 종료되었습니다.
ora-00472     pmon 프로세스가 오류로 종료되었습니다.
ora-00473     arch 프로세스가 오류로 종료되었습니다.
ora-00474     smon 프로세스가 오류로 종료되었습니다.
ora-00475     trwr 프로세스가 오류로 종료되었습니다.
ora-00476     reco 프로세스가 오류로 종료되었습니다.
ora-00477     snp* 프로세스가 오류로 종료되었습니다.
ora-00480     lck* 프로세스가 오류로 종료되었습니다.
ora-00483     정지 처리중 프로세스가 오류로 종료되었습니다.
ora-00568     인터럽트 처리기의 최대수를 초과했습니다.
ora-00574     osndnt: $cancel 실패 (break)
ora-00575     osndnt: $qio 실패 (send out-of-band break)
ora-00576     인-밴드 브레이크 프로토콜 오류
ora-00577     아웃-밴드 브레이크 프로토콜 오류
ora-00578     재설정 프로토콜 오류
ora-00579     osndnt: 서버가 잘못된 연결요구를 받았습니다.
ora-00580     프로토콜 버전이 일치하지 않습니다.
ora-00581     osndnt: 문맥 영역을 할당할 수 없습니다.
ora-00582     osndnt: 문맥 영역을 해제할 수 없습니다.
ora-00583     osndnt: $trnlog 실패
ora-00584     연결을 끊을 수 없습니다.
ora-00585     잘못된 유형의 호스트명입니다.
ora-00586     osndnt: lib$asn_wth_mbx 실패
ora-00587     원격 호스트에 연결할 수 없습니다.
ora-00588     호스트로부터의 메시지가 너무 짧습니다.
ora-00589     호스트로부터의 메시지가 잘못된 데이타 길이를 갖습니다.
ora-00590     호스트로부터의 메시지가 잘못된 데이타 유형을 갖습니다.
ora-00591     틀린 바이트 수가 기록되었습니다.
ora-00592     osndnt: $qio 실패 (mailbox queue)
ora-00593     osndnt: $dassgn 실패 (network device)
ora-00594     osndnt: $dassgn 실패 (mailbox)
ora-00595     osndnt: $qio 실패 (receive)
ora-00596     osndnt: $qio 실패 (send)
ora-00597     osndnt: $qio 실패 (mailbox requeue)
ora-00598     osndnt: $qio 실패 (mailbox read)
ora-00600     내부 오류 코드, 인수 : [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]
ora-00601     크린업 잠금이 충돌했습니다.
ora-00602     내부 프로그래밍 오류입니다 - bug로 등록하세요
ora-00603     oracle 서버 세션이 치명적인 오류로 종료되었습니다.
ora-00604     순환 sql 레벨 %s 에 오류가 발생했습니다.
ora-00606     내부 오류코드
ora-00701     데이타베이스의 기동에 필요한 개체를 변경할 수 없습니다.
ora-00702     부트스트랩 버전 %s가 버전 %s와 일치하지 않습니다.
ora-00703     행 캐쉬 인스턴스 잠금의 최대 수를 초과했습니다.
ora-00704     부트스트랩 프로세스 실패
ora-00816     오류 메세지 해석 오류입니다.
ora-00900     sql 문이 부적합합니다.
ora-00901     create 명령어가 부적합합니다.
ora-00902     데이타유형이 부적합합니다.
ora-00903     테이블명이 부적합합니다.
ora-00904     열명이 부적합합니다.
ora-00905     키워드가 없습니다.
ora-00906     좌괄호가 없습니다.
ora-00907     우괄호가 없습니다.
ora-00908     null 키워드가 없습니다.
ora-00909     인수의 개수가 부적합합니다.
ora-00910     데이타형에 지정된 길이가 너무 깁니다.
ora-00911     문자가 부적합합니다.
ora-00913     값의 수가 너무 많습니다.
ora-00914     add 키워드가 없습니다.
ora-00915     네트워크을 통한 dictionary table 액세스는 허가되지 않습니다.
ora-00917     코머가 누락되었습니다.
ora-00918     열의 정의가 애매합니다.
ora-00919     함수가 부적합합니다.
ora-00920     관계 연산자가 부적합합니다.
ora-00921     sql 명령어가 불완전합니다.
ora-00922     옵션이 부적합하거나 없습니다.
ora-00923     from 키워드가 있어야할 곳에 없습니다.
ora-00924     by 키워드가 없습니다.
ora-00925     into 키워드가 없습니다.
ora-00926     values 키워드가 없습니다.
ora-00927     등호가 없습니다.
ora-00928     select 키워드가 없습니다.
ora-00929     마침표(.)가 없습니다.
ora-00930    
ora-00931     식별자가 없습니다.
ora-00932     데이타 유형이 일치하지 않습니다.
ora-00933     sql 명령어가 올바르게 종료되지 않았습니다.
ora-00934     그룹 함수는 허가되지 않습니다.
ora-00935     그룹 함수의 내포 레벨이 너무 깊습니다.
ora-00936     식이 없습니다.
ora-00937     단일 그룹의 그룹 함수가 아닙니다.
ora-00938     함수의 인수가 충분하지 않습니다.
ora-00939     함수의 인수가 너무 많습니다.
ora-00940     alter 명령어가 부적합합니다.
ora-00941     클러스터 명이 없습니다.
ora-00942      테이블 또는 뷰가 존재하지 않습니다.
ora-00943     클러스터가 존재하지 않습니다.
ora-00944     클러스터 열의 수가 충분하지 않습니다.
ora-00945     지정한 클러스터 열이 존재하지 않습니다.
ora-00946     to 키워드가 없습니다.
ora-00947     값의 수가 충분하지 않습니다.
ora-00948     alter cluster 문은 제공되어 있지 않습니다.
ora-00949     원격 데이타베이스는 참조할 수 없습니다.
ora-00950     drop 옵션이 부적합합니다.
ora-00951     클러스터가 비어 있지 않습니다.
ora-00952     group 키워드가 없습니다.
ora-00953     색인명이 부적합합니다.
ora-00954     identified 키워드가 없습니다.
ora-00955     이미 사용된 개체명입니다.
ora-00956     감사 옵션이 부적합하거나 없습니다.
ora-00957     열명이 중복되었습니다.
ora-00958     check 키워드가 없습니다.
ora-00959     테이블 영역 %s 가 존재하지 않습니다.
ora-00960     선택 리스트에 애매한 열명이 있습니다.
ora-00962     너무 많은 group-by / order-by 식이 있습니다.
ora-00964     from 리스트에 테이블명이 없습니다.
ora-00965    
ora-00966     table 키워드가 없습니다.
ora-00967     where 키워드가 없습니다.
ora-00968     index 키워드가 없습니다.
ora-00969     on 키워드가 없습니다.
ora-00970     with 키워드가 없습니다.
ora-00971     set 키워드가 없습니다.
ora-00972     식별자의 길이가 너무 깁니다.
ora-00973     행수의 추정이 잘못되었습니다.
ora-00974     pctfree 값(백분율)이 부적합합니다.
ora-00975     날짜와 날짜의 가산은 할 수 없습니다.
ora-00976     level, prior, rownum 은 사용 할 수 없습니다.
ora-00977     감사 옵션이 중복되었습니다.
ora-00978     group by 구 없이 그룹 함수가 내포되었습니다.
ora-00979     group by 의 식이 없습니다.
ora-00980     동의어의 해석이 불가능합니다.
ora-00981     테이블 및 시스템 감사 옵션은 함께 지정될 수 없습니다.
ora-00982    
ora-00984     열을 사용할 수 없습니다.
ora-00985     프로그램명이 부적합합니다.
ora-00986     그룹명이 부적합하거나 없습니다.
ora-00987     사용자명이 부적합하거나 없습니다.
ora-00988     암호가 틀립니다.
ora-00989     사용자명에 대한 암호가 너무 많습니다.
ora-00990     권한이 부적합합니다.
ora-00991     mac 권한만이 프로시저에게 권한부여해 줍니다.
ora-00992     revoke 명령어의 형식이 부적합합니다.
ora-00993     grant 키워드가 없습니다.
ora-00994     option 키워드가 없습니다.
ora-00995     동의어의 식별자가 부적합합니다.
ora-00996     연접 연산자는 | 이 아니고 || 입니다.
ora-00997     long 데이타 유형은 사용할 수 없습니다.
ora-00998     이 식은 열의 별명과 함께 지정해야 합니다.
ora-00999     뷰명이 부적합합니다.
ora-01000     최대 열기 커서 수를 초과했습니다.
ora-01001     커서가 부적합합니다.
ora-01002     인출 시퀀스가 틀립니다.
ora-01003     해석된 문이 없습니다.
ora-01004     디폴트 사용자명 사용 불가. 로그온이 허락되지 않습니다.
ora-01005     널 암호가 입력되었습니다 로그온이 허락되지 않습니다.
ora-01006     바인드 변수가 없습니다.
ora-01007     변수가 선택 리스트에 없습니다.
ora-01008     모든 한계변수가 아닙니다.
ora-01009     필수 파라미터가 없습니다.
ora-01010     oci 조작이 부적합합니다.
ora-01011     v6 서버와 교신할때 v7 호환성 모드를 사용할 수 없습니다.
ora-01012     로그온되어 있지 않습니다.
ora-01013     현 조작의 취소가 요구되었습니다.
ora-01014     oracle의 정지 처리가 진행중입니다.
ora-01015     로그온이 순환적으로 호출되었습니다.
ora-01016     이함수는 인출 이후에만 호출될 수 있습니다.
ora-01017     사용자명/암호가 부적합, 로그온할 수 없습니다.
ora-01018     long 데이타 유형의 열이 아닙니다.
ora-01019     사용자쪽의 기억영역을 할당할 수 없습니다.
ora-01020     문맥의 상태가 불명확합니다.
ora-01021     지정한 문맥 크기가 부적합합니다.
ora-01022     이 구성에 데이타베이스 작업이 지원되지 않습니다.
ora-01023     커서 문맥가 없습니다부당한 커서번호)
ora-01024     oci 콜의 데이타 유형은 부적합합니다.
ora-01025     upi 파라미터가 부적합합니다.
ora-01026     바인드 목록에 크기가 2000이상인 다중 버퍼
ora-01027     데이타 정의에서는 바인드 변수를 사용할 수 없습니다.
ora-01028     내부 투 태스크(two task) 오류
ora-01029     내부 투 태스크(two task) 오류
ora-01030     select ... into 변수가 없습니다.
ora-01031     권한이 불충분합니다.
ora-01032     사용자 번호가 존재하지 않습니다.
ora-01033     oracle의 초기화 또는 정지 처리가 진행중입니다.
ora-01034     oracle을 사용할 수 없습니다.
ora-01035     oracle은 restricted session 권한을 갖는 사용자만 사용 가능합니다.
ora-01036     잘못된 변수명/번호
ora-01037     최대 커서 메모리가 초과되었습니다.
ora-01038     데이타베이스 화일 버전 %s에 oracle 버전 %s으로 기록할 수 없습니다.
ora-01039     사용되지 않는 오류
ora-01040     암호에 잘못된 문자가 있습니다 로그온을 할 수 없습니다.
ora-01041     내부오류. hostdef 확장이 존재하지 않습니다.
ora-01042     개방된 커서와 함께 세션을 분리하는 것은 허용되지 않습니다.
ora-01043     사용자쪽의 기억영역 파괴 [%s], [%s], [%s], [%s]
ora-01044     버퍼의 크기 %s (한계가 변수 %s)가 최대의 %s를 초과했습니다.
ora-01045     사용자 %s는 create session 권한을 가지고있지 않음; 로그온이 거절되었습니다.
ora-01046     확장할 문맥 영역을 획득할 수 없습니다.
ora-01047     위에 오류는 스키마=%s, 패키지=%s, 프로시저=%s에서 발생된 것입니다.
ora-01048     주어진 컨텍스트에서 지정된 프로시저를 찾을 수 없습니다.
ora-01049     스트림된 rpc에서 이름으로 바인드한것은 지원되지 않습니다.
ora-01050     문맥 영역을 개방하기 위한 영역을 획득할 수 없습니다.
ora-01051     잘못된 지연 rpc 버퍼 포맷
ora-01053     사용자 기억 영역 주소를 읽을 수 없습니다.
ora-01054     사용자 기억 영역 주소에 기록할 수 없습니다.
ora-01057     내부의 new upi 인터페이스 오류
ora-01058     internal new upi interface error
ora-01059     바인드 또는 실행전에 구문분석이 필요합니다.
ora-01060     배열 바인드 또는 실행이 허용되지 않습니다.
ora-01070     서버용으로 구버전의 오라클을 사용
ora-01071     oracle을 기동하지 않으면 조작 실행이 불가 합니다.
ora-01072     oracle은 기동중이 아닙니다 정지할 수 없습니다.
ora-01073     연결 오류. 콜(call)의 유형을 인식할 수 없습니다.
ora-01074     oracle은 정지되지 않습니다 먼저 로그오프해 주십시오
ora-01075     이미 로그온되어 있습니다.
ora-01076     단일 프로세스에 대한 복수 로그온은 제공되지 않습니다.
ora-01077     백그라운드 프로세스 초기화 오류입니다.
ora-01078     시스템 파라미터 처리 오류입니다.
ora-01079     oracle 데이타베이스가 작성되지 않았음 - 작업이 비정상 종료되었습니다.
ora-01080     oracle 정지중 오류가 발생했습니다.
ora-01081     이미 기동중인 oracle을 기동하려 했습니다.
ora-01082     row_locking = always 기능은 tps 옵션이 없는 oracle에서는 지원되지않습니다.
ora-01083     파라미터 값 %s는 다른 서버들의 값과 불일치합니다.
ora-01084     oci 호출에 부적당한 인수가 있습니다.
ora-01085     %s에 대한 지연 원격 프로시저 호출(rpc)에서 오류 발생
ora-01086     세이브포인트 %s 는 설정되어 있지 않습니다.
ora-01087     현재 oracle에 로그온되어 있습니다 기동할 수 없습니다.
ora-01088     액티브 프로세스가 있기 때문에 oracle을 정지할 수 없습니다.
ora-01089     정지 처리(즉시)중입니다 조작은 허가되지 않습니다.
ora-01090     정지 처리중입니다 연결할 수 없습니다.
ora-01091     기동중에 오류가 발생했습니다.
ora-01092     오라클 인스턴스 종료 분리가 되었습니다.
ora-01093     alter database close 문은 연결된 세션이 없는 경우에만 가능합니다.
ora-01094     alter database close 문이 수행중 입니다 연결은 허용되지 않습니다.
ora-01095     dml 문이 0개의 행을 처리 했습니다.
ora-01096     프로그램 버전 (%s)과 인스턴스 (%s)가 호환성이 없습니다.
ora-01097     트랜잭션 도중에 shutdown할 수 없습니다- 먼저 커밋 혹은 롤백하십시오
ora-01098     long insert중에 프로그램 인터페이스 오류
ora-01099     단일 프로세스 모드로 기동된 데이타베이스는 shares 모드로 마운트할 수 없습니다.
ora-01100     데이타베이스가 이미 마운트 되었습니다.
ora-01101     다른 인스턴스로 부터 생성된 데이타베이스가 현재 마운트 되었습니다.
ora-01102     데이타베이스가 exclusive 모드로 마운트할 수 없습니다.
ora-01103     제어 화일의 데이타베이스명 %s는 %s가 아닙니다.
ora-01104     제어 화일의 수(%s)가 %s 와 일치하지 않습니다.
ora-01105     올리기는 다른 인스턴스에 의해 마운트하는 것과 호환성이 없습니다.
ora-01106     내리기를 하기전에 데이타베이스를 디스마운트 합니다.
ora-01107     매체 복구를 위해 데이타베이스를 마운트해야 합니다.
ora-01108     화일 %s가 매체 복구 중에 있습니다.
ora-01109     데이타베이스가 개방되지 않습니다.
ora-01110     데이타 화일 %s: %s
ora-01111     데이타 화일 %s의 이름을 모릅니다- 올바른 화일로 재명명 하십시오.
ora-01112     매체 복구 처리가 개시되지 않았습니다.
ora-01113     화일 %s가 매체 복구되어야 합니다.
ora-01114     화일 %s의 블록쓰기 io 오류입니다블록 번호 %s).
ora-01115     화일 %s의 블록(블록 번호 %s) 읽기 io 오류입니다.
ora-01116     데이타베이스 화일 %s의 개방 오류입니다.
ora-01117     추가하는 화일 %s 의 블록 크기 %s 는 부적합합니다 제한은 %s 입니다.
ora-01118     데이타베이스 화일을 더 이상 등록할 수 없습니다 제한 %s 를 초과했습니다.
ora-01119     데이타베이스 화일 %s 의 작성 오류입니다.
ora-01120     온라인 데이타베이스 화일 %s은 삭제할 수 없습니다.
ora-01121     데이타 화일 %s를 재명명할 수 없습니다- 화일이 사용중이거나 복구중입니다.
ora-01122     데이타 화일 %s의 검증 체크에 실패 했습니다.
ora-01123     온라인 백업을 개시할 수 없습니다 매체 복구가 사용 불가로 되어 있습니다.
ora-01124     데이타 화일 %s을 복구할 수 없음 - 화일이 사용중이거나 복구중입니다.
ora-01125     매체 복구를 사용불가할 수 없음. 화일 %s 가 온라인 백업으로 설정됨.
ora-01126     데이타베이스는 exclusive로 마운트하고 개방하지 말아야 합니다.
ora-01127     데이타베이스명 %s가 최대 문자수 %s를 초과했습니다.
ora-01128     온라인 백업을 시작할 수 없음 - 화일 %s가 오프라인입니다.
ora-01129     디폴트 또는 임시 테이블 영역이 존재하지 않습니다.
ora-01130     데이타베이스 화일 버전 %s 는 oracle 버전 %s 와 호환되지 않습니다.
ora-01131     db_files 파라미터의 값 %s 가 최대수 %s 를 초과했습니다.
ora-01132     데이타베이스 화일명 %s 의 길이가 최대 문자수 %s 를 초과했습니다.
ora-01133     로그 화일명 %s 의 길이가 최대 문자수 %s 를 초과했습니다.
ora-01134     데이타베이스가 다른 인스턴스에 의해 배타 모드로 마운트했습니다.
ora-01135     dml/질의로 액세스된 화일 %s 는 오프 라인입니다.
ora-01136     화일 %s의 명시된 크기(%s 블록)가 원래 크기 %s 블록보다 작습니다.
ora-01137     데이타 화일 %s가 오프라인으로 되고 있는 중입니다.
ora-01138     데이타베이스가 이 인스턴스로 열거나 다른 인스턴스에 대해 닫아야 합니다.
ora-01139     resetlogs 옵션은 불완전한 데이타베이스의 복구 후에만 유효합니다.
ora-01140     온라인 백업을 종료할 수 없음 - 모든 화일이 오프라인입니다.
ora-01141     데이타 화일 %s의 재명명 오류 - 새로운 화일 %s 가 없습니다.
ora-01142     온라인 백업을 종료할 수 없음 - 백업할 수 있는 상태의 화일이 없습니다.
ora-01143     매체 복구를 사용불가하게할 수 없습니다 화일 %s가 매체복구를 필요로 합니다.
ora-01144     화일크기(%s 블록)가 최대치 %s 블록을 초과합니다.
ora-01145     매체 복구가 사용 가능하지 않으면 즉시 오프라인으로 할 수 없습니다.
ora-01146     온라인 백업을 시작할 수 없습니다 - 화일 %s가 이미 백업중에 있습니다.
ora-01147     system 테이블 영역 화일 %s가 오프 라인입니다.
ora-01148     이 작업을 하려면 데이타베이스가 exclusive 모드로 마운트해야 합니다.
ora-01149     정지처리 불가 - 화일 %s를 온라인 백업중 입니다.
ora-01150     쓰기 방지를 할수 없음 - 화일 %s를 온라인 백업중 입니다.
ora-01151     블록을 복구하려면 미디어 복구를 사용하고 필요하면 백업을 사용하십시오
ora-01152     화일 %s가 충분한 이전 백업으로 복구되지 않았습니다
ora-01153     비호환 매체 복구가 동작 상태입니다.
ora-01154     데이타베이스는 사용중 - 개방, 클로즈, 마운트, 디스마운트 할 수 없습니다.
ora-01155     데이타베이스는 개방, 클로즈, 마운트 혹은 디스마운트 중 입니다.
ora-01156     진행중인 복구 작업이 화일 액세스를 필요로 할 수 있습니다.
ora-01157     데이타 화일 %s를 식별할 수 없습니다- 화일이 발견되지 않음
ora-01158     데이타베이스 %s 가 이미 마운트했습니다.
ora-01159     화일이 동일한 데이타베이스의 화일이 아닙니다- 데이타베이스 id가 잘못됨.
ora-01160     화일이 %s가 아닙니다.
ora-01161     화일헤더에 있는 데이타베이스명 %s가 주어진 이름 %s 와 일치하지 않습니다.
ora-01162     화일 헤더에 블록 크기 %s가 db_block_size(%s)와 일치하지 않습니다.
ora-01163     size 절에 %s (블록)이 지정되었으나 헤더 %s와 일치해야 합니다.
ora-01164     maxlogfiles는 %s 를 초과할 수 없습니다.
ora-01165     maxdatafiles는 %s 를 초과할 수 없습니다.
ora-01166     화일번호 %s가 %s (%s)보다 큽니다.
ora-01167     두개의 화일들이 같은 화일 그룹번호 이거나 같은 화일입니다.
ora-01168     물리 블록 크기 %s가 다른 멤버들의 크기 %s와 일치하지 않습니다.
ora-01169     datafile 번호 1번이 없습니다.
ora-01170     화일이 존재하지 않습니다 %s
ora-01171     체크포인트 오류 때문에 데이타 화일 %s이 오프라인됩니다.
ora-01172     쓰레드 %s의 복구가 블록 %s(화일 %s의)에서 더이상 진행되지 못합니다.
ora-01173     데이타 dictionary
ora-01174     db_file %s는 호환성을 위해서 %s가 되어야 합니다.
ora-01175     데이타 dictionary가 인스턴스에서 허용하는 %s 보다 많은 수의 화일을 포함합니다.
ora-01176     데이타 dictionary가 제어 화일에서 허용하는 %s 보다 많은 수의 화일을 포함합니다.
ora-01177     데이타 화일이 dictionary와 일치하지 않습니다- 아마도 오래된 것입니다.
ora-01178     화일 %s가 마지막 create controlfile 이전에 생성됐음. 재 생성할 수 없습니다.
ora-01179     화일 %s 가 존재하지 않습니다.
ora-01180     데이타 화일 1을 생성할 수 없습니다.
ora-01181     최후의 resetlogs 이전에 생성된 화일 %s를 재생성할 수 없습니다.
ora-01182     데이타베이스 화일 %s를 생성할 수 없음 - 사용중이거나 복구중입니다.
ora-01183     shared모드로 데이타베이스를 마운트할 수 없습니다.
ora-01184     로그화일 그룹 %s는 이미 존재합니다.
ora-01185     로그화일 그룹 %s는 부적절합니다.
ora-01186     화일 %s의 검증 테스트에 실패했습니다.
ora-01187     검증 테스트에 실패했기 때문에 화일 %s를 읽을 수 없습니다.
ora-01188     헤더내의 블록 크기 %s가 실제 물리블록 크기 %s와 맞지 않습니다.
ora-01189     이전 화일과 다른 resetlogs가 사용되었습니다.
ora-01190     제어 화일 혹은 데이타 화일 %s는 마지막 resetlogs 이전의 것입니다.
ora-01191     화일 %s는 이미 오프라인임 - 정상적인 오프라인을 할 수 없습니다.
ora-01192     최소한 하나의 이용 가능한 쓰레드를 가져야합니다.
ora-01193     화일 %s는 복구 시작시 인식된 화일이 아닙니다.
ora-01194     화일 %s가 일관성을 갖기 위해서는 더 많은 복구가 필요로 합니다.
ora-01195     화일 %s의 온라인 백업은 일관성을 갖기위해 더 많은 복구가 필요로 합니다.
ora-01196     매체복구 세션의 실패로 인하여 화일 %s의 일관성이 결여되어 있습니다.
ora-01197     쓰레드 %s는 하나의 로그만을 포함하고 있습니다.
ora-01198     resetlogs인 경우 로그화일에 대한 크기를 지정하여야 합니다.
ora-01199     화일 %s는 온라인 백업 모드가 아닙니다.
ora-01200     실제 화일크기 %s는 맞는 크기인 %s 블록보다 작습니다.
ora-01201     헤더내의 화일 크기 %s가 제어화일내의 크기 %s와 일치하지 않습니다.
ora-01202     화일의 구현이 잘못됨 - 작성 시각이 틀립니다.
ora-01203     화일의 구현이 잘못됨 - 작성 scn이 틀립니다.
ora-01204     화일 번호가 %s (%s가 아님) - 틀린 화일입니다.
ora-01205     데이타 화일이 아님 - 헤더내의 유형 번호가 %s입니다.
ora-01206     화일은 이 데이타베이스의 일부가 아님 - 데이타베이스 id가 틀립니다.
ora-01207     화일이 제어화일보다 최근의 것임 - 오래된 제어화일입니다.
ora-01208     데이타 화일이 구버전임 - 현 버전을 액세스하지 않았습니다.
ora-01209     데이타 화일이 마지막 resetlogs 이전의 것입니다.
ora-01210     데이타 화일의 헤더가 매체 붕괴되었습니다.
ora-01211     버전 6의 데이타 화일이 버전7으로의 변환 화일이 아닙니다.
ora-01212     maxlogmembers는 %s를 초과할 수 없습니다.
ora-01213     maxinstance는 %s를 초과할 수 없습니다.
ora-01214     maxloghistory는 %s를 초과할 수 없습니다.
ora-01215     create controlfile이후의 가용 쓰레드 %s가 빠졌습니다.
ora-01216     create controlfile이후 쓰레드 %s는 사용불가되어야합니다.
ora-01217     로그화일 멤버가 다른 로그화일 그룹에 속해있습니다.
ora-01218     로그화일 멤버는 동일한 시간때에 만든것이 아닙니다.
ora-01219     데이타베이스가 열지 않았음: 고정 테이블/뷰에 대해서만 조회가 가능합니다.
ora-01220     데이테베이스가 개방 되기전에는, 화일을 기본으로하는 소트가 부적합합니다.
ora-01221     데이타 화일 %s는 백그라운드 프로세스에 대해 동일 화일이 아닙니다.
ora-01222     %s의 maxinstances는 maxlogfiles가 최소 %s이어야함(%s가 아님)
ora-01223     새로운 데이타베이스명을 부여하기 위해서는 resetlogs를 지정하여야 합니다.
ora-01224     헤더 %s내의 그룹번호가 group %s와 맞지 않습니다.
ora-01225     쓰레드 번호 %s가 maxinstances %s 보다 큽니다.
ora-01226     로그 멤버의 화일헤더가 다른 멤버와 일치하지 않습니다.
ora-01227     로그 %s는 다른 로그와 일치하지 않습니다.
ora-01228     기초 데이테베이스를 설치하려면 set database 옵션이 필요합니다.
ora-01229     데이타 화일 %s가 로그와 일치하지 않습니다.
ora-01230     읽기 전용으로 만들수 없습니다- %s 화일이 오프라인입니다.
ora-01231     쓰기 전용으로 만들수 없습니다- %s 화일이 오프라인입니다.
ora-01232     온라인 백업을 수행할 수 없습니다- %s 화일은 읽기 전용입니다.
ora-01233     %s 화일은 읽기 전용입니다- 컨트롤화일 백업을 사용해서 복구할 수 없습니다.
ora-01234     화일 %s의 백업을 종료할 수 없습니다 - 화일을 사용중이거나 복구중입니다.
ora-01235     %s 화일에 대한 end backup은 실패하고 %s에 대해서는 성공했습니다.
ora-01237     데이타화일 %s를 확장할 수 없습니다.
ora-01238     데이타화일 %s를 축소할 수 없습니다.
ora-01239     데이터베이스는 외부 캐시를 사용하기 위해서 archivelog 모드로 되어 있어야 합니다.
ora-01240     하나의 명령어에 너무 많은 데이터 화일을 추가합니다.
ora-01241     외부 캐시가 죽었습니다.
ora-01242     데이터 화일이 메디아 실패를 받았습니다: 데이터베이스는 noarchivelog 모드입니다.
ora-01243     시스템 테이블스페이스 화일이 메디아 실패를 받았습니다.
ora-01244     메디아 복구에 의해서 제어화일에 이름 없는 데이터화일이 추가되었습니다.
ora-01245     오프라인 화일 %s 은 resetlogs이 끝나면 없어집니다.
ora-01400     행의 입력으로 필수 열(not null)에 값이 지정되지 않았습니다.
ora-01401     열에 입력한 값이 너무 큽니다.
ora-01402     뷰의 with check option의 조건에 위배 됩니다.
ora-01403     데이타가 없습니다.
ora-01404     alter column은 색인을 너무 크게 만들 수 있습니다.
ora-01405     인출된 열의 값은 null입니다.
ora-01406     인출된 열의 값이 절사되었습니다.
ora-01407     입력 필수 열(not null)은 null로 갱신할 수 없습니다.
ora-01408     열 리스트에는 이미 색인이 작성되어 있습니다.
ora-01409     nosort 옵션은 사용할 수 없습니다 행이 오름차순으로 되어 있지 않습니다.
ora-01410     rowid가 부적합합니다.
ora-01411     표시기내에 열의 길이를 저장할 수 없습니다.
ora-01412     이 데이타 유형에 대해서는 0길이가 허용되지 않습니다.
ora-01413     팩형 십진수 버퍼안의 값이 부적합합니다.
ora-01414     배열을 바인드 할때 배열 길이가 부적합합니다.
ora-01416     두 개의 테이블을 outer-join할 수 없습니다.
ora-01417     하나의 테이블은 하나의 다른 테이블과 outer-join할 수 있습니다.
ora-01418     지정한 색인는 존재하지 않습니다.
ora-01419     datdts: 형식 코드 오류입니다.
ora-01420     datstd: 형식 코드 오류입니다.
ora-01421     datrnd/dattrn: 정도 지정자 오류입니다.
ora-01422     실제 인출은 요구된 것보다 많은 수의 행을 추출합니다.
ora-01423     실제 인출에서 여분의 행을 검사하는 중에 오류가 검출되었습니다.
ora-01424     에스케이프 문자 뒤에 누락 혹은 부당한 문자가 있습니다.
ora-01425     에스케이프 문자는 1자리 문자 스트링이어야 합니다.
ora-01426     수치 오버플로우
ora-01427     단일 행 부속 질의에 의해 2개 이상의 행이 리턴되었습니다.
ora-01428     인수 %s가 범위를 벗어났습니다.
ora-01430     추가하려는 열이 이미 테이블에 존재합니다.
ora-01431     grant 명령어 내부 불일치 오류입니다.
ora-01432     삭제할 공개 동의어가 존재하지 않습니다.
ora-01433     작성한 동의어가 이미 정의되어 있습니다.
ora-01434     삭제할 비공개 동의어가 존재하지 않습니다.
ora-01435     사용자가 존재하지 않습니다.
ora-01436     connect by의 루프가 발생되었습니다.
ora-01437     결합은 connect by와 함께 지정할 수 없습니다.
ora-01438     지정한 정도를 초과한 값이 열에 지정되었습니다.
ora-01439     데이타 유형을 변경할 열은 비어 있어야 합니다.
ora-01440     정도 또는 자리수를 축소할 열은 비어 있어야 합니다.
ora-01441     길이를 짧게 변경할 열의 값은 null이어야 합니다.
ora-01442     변경하고자 하는 열이 이미 not null입니다.
ora-01443     내부 오류 : 뷰 열의 데이타 유형이 부적합합니다.
ora-01444     내부 오류 : 내부 데이타 유형와 외부 데이타 유형은 부적합합니다.
ora-01445     키-보전 테이블 없이 결합 뷰으로 부터 rowid를 선택할 수 없습니다.
ora-01446     distinct, group by 등을 포함하는 뷰로부터 rowid를 선택할 수 없습니다.
ora-01447     클러스터 열에 alter table 문을 사용할 수 없습니다.
ora-01448     데이타 유형을 변경하기 전에 색인을 삭제해야 합니다.
ora-01449     열이 null값을 포함하고 있습니다 not null로 변경할 수 없습니다.
ora-01450     키의 최대 길이(%s)를 초과했습니다.
ora-01451     열이 이미 null로 되어 있습니다.
ora-01452     중복 키가 있습니다. 유일한 색인을 작성할 수 없습니다.
ora-01453     set transaction 사용시에는 트랜잭션의 최초문장 이어야 합니다.
ora-01454     수치 데이타 유형으로 변환할 수 없습니다.
ora-01455     열의 변환에 의해 정수 데이타 유형이 오버플로우되었습니다.
ora-01456     read only 트랜잭션은 삽입/삭제/갱신할 수 없습니다.
ora-01457     열의 변환에 의해 decimal 데이타 유형이 오버플로우되었습니다.
ora-01458     가변장 스트링의 지정된 길이가 부적합합니다.
ora-01459     가변장 스트링의 길이가 부적합합니다.
ora-01460     요구된 변환은 실행될 수 없습니다.
ora-01461     long 값은 long 열에만 입력할 수 있습니다.
ora-01462     2000 문자 이상은 입력할 수 없습니다.
ora-01463     자신에 대한 권한의 허가나 취소는 불가능합니다.
ora-01464     테이블 또는 뷰의 grant 오류입니다.
ora-01465     16진수의 지정이 부적합합니다.
ora-01466     테이블 정의가 변경되었습니다 데이타를 읽을 수 없습니다.
ora-01467     정렬 키가 너무 깁니다.
ora-01468     outer-join된 테이블은 1개만 지정할 수 있습니다.
ora-01469     prior의 뒤에는 열 명을 지정해 주십시오
ora-01471     개체와 같은 이름의 동의어는 작성할 수 없습니다.
ora-01472     connect by는 distinct, group by 를 동반한 뷰에 사용할 수 없습니다.
ora-01473     connect by 구에 부속 질의를 지정할 수 없습니다.
ora-01474     connect by 없이 start with 나 prior 는 지정할 수 없습니다.
ora-01475     바인드 변수의 데이타 유형 변경을 위해서는 커서를 재구문분석을 해야 합니다.
ora-01476     제수가 0 입니다.
ora-01477     사용자 데이타 영역 기술자가 너무 큽니다.
ora-01478     long 열은 배열 바인드에 사용할 수 없습니다.
ora-01479     버퍼내의 마지막 문자가 널(null)이 아닙니다.
ora-01480     str 바인드 값에 종료의 널이 없습니다.
ora-01481     숫자 형식 모델이 부적합합니다.
ora-01482     지정된 문자세트는 제공하지 않습니다.
ora-01483     date 또는 number 바인드 변수의 길이가 부적합합니다.
ora-01484     배열은 pl/sql문 범위에서만 해야 합니다.
ora-01485     실행 바인드 길이가 컴파일 바인드 길이와 다릅니다.
ora-01486     배열요소 크기가 너무 큽니다.
ora-01487     팩형 십진수가 제공된 버퍼에 비해 너무 큽니다.
ora-01488     부적절한 팩형 십진수 입니다.
ora-01489     스트링 연결의 결과가 너무 깁니다.
ora-01490     부적합한 analyze 명령입니다.
ora-01491     cascade 옵션이 부적합합니다.
ora-01492     현 트랜잭션이 이미 롤백 세그먼트에 연결되어 있습니다.
ora-01493     명시된 sample 길이가 부적합합니다.
ora-01494     지정된 size가 부적당합니다.
ora-01495     지정된 연결행 테이블이 없습니다.
ora-01496     지정된 연결행 테이블 형식이 틀립니다.
ora-01497     analyze cluster에 대한 옵션이 잘못되었습니다.
ora-01498     블록 체크 실패 - 트래스 화일을 보십시오
ora-01499     테이블/색인의 교차 참조 실패 - 트래스 화일을 보십시오
ora-01500     날짜/시간의 획득 오류입니다.
ora-01501     create database 문 오류입니다.
ora-01502     색인 %s는 직접 로드 상태입니다.
ora-01503     create controlfile이 실패했습니다.
ora-01504     데이타베이스명 %s가 db_name 파라미터 %s와 맞지않습니다.
ora-01505     로그 화일 등록 오류입니다.
ora-01506     데이타베이스 명을 올바르게 지정해 주십시오.
ora-01507     데이타베이스가 마운트하지 않았습니다.
ora-01508     화일 %s 의 줄 %s 에 오류. 데이타베이스를 생성할 수 없습니다.
ora-01509     지정한 이름 %s 가 실제의 이름 %s 와 일치하지 않습니다.
ora-01510     로그 화일 삭제 오류입니다.
ora-01511     로그/데이타 화일의 재명명 오류입니다.
ora-01512     로드 화일 %s의 재명명 오류 - 새로운 화일 %s가 없습니다.
ora-01513     운영 시스템으로 부터 부정확한 현시각이 보내졌습니다.
ora-01514     로그 명세에 오류: 그런 로그가 없습니다.
ora-01515     로그 그룹 %s의 삭제시 오류. 그런 로그가 없습니다.
ora-01516     로그/데이타 화일 %s 는 존재하지 않습니다.
ora-01517     로그 멤버: %s
ora-01518     2개 이상의 로그 화일을 create database 에 지정해 주십시오.
ora-01519     오류 발생(화일 %s 의 줄 %s 부근)
ora-01520     추가할 데이타 화일의 수(%s)가 최대수 %s 를 초과했습니다.
ora-01521     데이타 화일의 등록중 오류가 발생했습니다.
ora-01522     재명명할 화일 %s 가 없습니다.
ora-01523     데이타 화일 %s 는 이미 데이타베이스의 일부입니다. 재명명할 수 없습니다.
ora-01524     %s로 데이타 화일을 생성할 수 없음 - 화일이 이미 데이타베이스의 부분입니다.
ora-01525     데이타 화일의 재명명중 오류가 발생했습니다.
ora-01526     화일 %s 의 열기 오류가 발생했습니다.
ora-01527     화일을 읽는 도중 오류가 발생했습니다.
ora-01528     sql 문의 처리중 eof 오류입니다.
ora-01529     화일 %s 의 클로즈중 오류가 발생했습니다.
ora-01530     이 인스턴스는 이미 데이타베이스를 마운트했습니다.
ora-01531     이 인스턴스는 이미 데이타베이스를 개방했습니다.
ora-01532     인스턴스가 기동되어 있습니다. 데이타베이스를 생성할 수 없습니다.
ora-01533     화일 %s 는 테이블 영역에 속해 있지 않습니다. 재명명할 수 없습니다.
ora-01534     롤백 세그먼트 %s 가 존재하지 않습니다.
ora-01535     롤백 세그먼트 %s 는 이미 존재합니다.
ora-01536     테이블 영역 %s 에 대한 영역 할당량이 초과됐습니다.
ora-01537     데이타 화일 %s 는 이미 데이타베이스의 일부입니다 등록할 수 없습니다.
ora-01538     롤백 세그먼트를 획득할 수 없습니다.
ora-01539     테이블 영역 %s 가 온라인이 아닙니다.
ora-01540     테이블 영역 %s 가 오프라인이 아닙니다.
ora-01541     system 테이블 영역은 오프라인될 수 없습니다 필요하면 중지 하십시오
ora-01542     테이블 영역 %s 가 오프라인입니다. 영역을 할당할 수 없습니다.
ora-01543     테이블 영역 %s 는 이미 존재하고 있습니다.
ora-01544     시스템 롤백 세그먼트는 삭제할 수 없습니다.
ora-01545     롤백 세그먼트 %s 는 사용할 수 없습니다.
ora-01546     테이블 영역에 액티브 롤백 세그먼트 %s 가 있습니다.
ora-01548     액티브 롤백 세그먼트 %s 가 존재함, 테이블 영역의 삭제를 종료하십시오.
ora-01549     테이블 영역이 비어있지 않으므로 including contents를 사용해 주십시오.
ora-01550     시스템 테이블 영역은 삭제할 수 없습니다.
ora-01551     롤백 세그먼트 확장 오류입니다.
ora-01552     시스템 테이블 영역이 아닌 %s 에 시스템 롤백 세그먼트를 사용할 수 없습니다.
ora-01553     maxextents는 현재 할당된 %s 엑스텐트 수 이상이어야 합니다.
ora-01554     트랜잭션 슬롯이 없습니다.
ora-01555     스냅샷이 너무 오래 되었습니다(롤백 세그먼트가 너무 작습니다)
ora-01556     롤백 세그먼트를 위한 minextents는 1보다 커야만 합니다.
ora-01557     롤백 세그먼트 엑스텐트는 최저 %s 블록이 필요합니다.
ora-01558     롤백 세그먼트 %s 에 트랜잭션 번호가 없습니다.
ora-01559     롤백 세그먼트의 maxextents 는 2 이상입니다.
ora-01560     글로벌 해쉬 테이블의 크기가 %s와 일치하지 않습니다 (%s !=%s)
ora-01561     지정된 테이블 영역중의 개체가 삭제되지 않았습니다.
ora-01562     롤백 세그먼트 확장 실패입니다 (id = %s)
ora-01563     키워드 public 을 사용해 주십시오
ora-01564     롤백 세그먼트는 public 이 아닙니다.
ora-01565     화일 %s 의 식별 오류가 발생했습니다.
ora-01566     drop logfile에 화일이 2회 이상 지정되었습니다.
ora-01567     로그 %s를 삭제하면 쓰레드 %s에 남는 로그 화일이 2개 미만으로 됩니다.
ora-01568     public에 영역 할당량을 설정할 수 없습니다.
ora-01569     시스템 dictionary 테이블에 대한 데이타 화일이 너무 작습니다.
ora-01570     minextents는 현재 할당된 %s보다 클 수 없습니다.
ora-01571     로그 레코드 버전 %s 가 oracle의 버전 %s 과 호환되지 않습니다.
ora-01572     롤백 세그먼트용 글로벌 해쉬 테이블의 크기 %s가 롤백 세그먼트 번호 %s 에 대해 너무 작음
ora-01573     인스턴스의 정지 처리가 진행중. 더 이상의 변경은 허용되지 않습니다.
ora-01574     최대 동시 실행 트랜잭션 수를 초과했습니다.
ora-01575     영역 관리 자원의 대기중 시간이 초과되었습니다.
ora-01576     인스턴스 잠금 프로토콜 버전 %s는 oracle의 버전 %s 와 호환되지 않습니다.
ora-01577     로그 화일 %s는 이미 데이타베이스의 일부입니다 등록이 불가능합니다.
ora-01578     oracle 데이타 블록이 파손되었습니다 (화일 번호 %s, 블록 번호 %s)
ora-01579     복구중 기록(write) 오류가 발생했습니다.
ora-01580     제어 화일의 백업 화일 %s 를 작성하는 중에 오류가 발생했습니다.
ora-01581     이미 할당된 롤백 세그먼트(%s) 새로운 익스텐트(%s)를 사용하려 시도했습니다.
ora-01582     백업을 하기위해 제어 화일을 열 수 없습니다.
ora-01583     백업될 제어 화일의 블록 크기를 획득할 수 없습니다.
ora-01584     백업될 제어 화일의 화일 크기를 획득할 수 없습니다.
ora-01585     백업 화일 %s 를 인식할 수 없습니다.
ora-01586     백업을 하기위한 수신 화일 %s을 열 수 없습니다.
ora-01587     제어 화일의 백업 화일 복제중 오류가 발생했습니다.
ora-01588     데이타베이스를 열기 위해서는 resetlogs 옵션을 사용해야 합니다.
ora-01589     데이타베이스를 열기 위해서는 resetlogs/noresetlogs 옵션을 사용해야 함
ora-01590     가용 세그멘트 수(%s)가 최대치인 %s 를 초과합니다.
ora-01591     잠금이 in-doubt 분산 트랜잭션 %s에 주어졌습니다.
ora-01592     버전 6의 롤백 세그먼트(%s)를 oracle7 포맷으로 변환시 오류 발생
ora-01593     롤백 세그먼트의 최적크기(%s 블록)가 초기크기 계산(%s 블록)보다 작습니다.
ora-01594     해제될 롤백 세그먼트(%s) 익스텐트(%s)를 연결하려함
ora-01595     익스텐스(%s)(롤백 세그먼트 (%s)의) 해제시 오류
ora-01596     %s 파라미터에 시스템을 지정할 수 없습니다.
ora-01597     시스템 롤백 세그먼트를 온라인 혹은 오프라인시킬 수 없습니다.
ora-01598     롤백 세그먼트 %s가 온라인이 아닙니다.
ora-01599     롤백 세그먼트(%s)를 획득하는데 실패, 캐쉬 영역이 꽉찼습니다현재(%s)엔트리를 가짐)
ora-01600     많아야 하나의 %s (gc_files_to_locks의 %s절에)
ora-01601     gc_files_to_locks의 %s절에 부당한 버켓(bucket) 크기
ora-01602     gc_files_to_locks에 예정된 것보다 gc_db_locks에 더 많은 잠금임
ora-01603     gc_files_to_locks의 %s절에 부당한 그룹크기
ora-01604     gc_files_to_locks의 %s절에 부당한 화일 번호 범위
ora-01605     gc_files_to_locks의 %s절에 화일 번호 누락
ora-01606     gc_files_to_lock가 마운트한 다른 인스턴스의 그것과 동일하지 않습니다.
ora-01607     gc_lck_procs (%s)가 다른 인스턴스 (%s)와 같지 않습니다.
ora-01608     롤백 세그먼트 %s를 온라인화할 수 없음. 상태는 (%s)
ora-01609     로그 %s는 쓰레드 %s에 대한 현 로그 - 멤버를 삭제할 수 없습니다.
ora-01610     backup controlfile 옵션을 이용해서 복구가 끝나야만 합니다.
ora-01611     쓰레드번호 %s는 부적절함 - %s보다 커서는 안됩니다.
ora-01612     쓰레드 %s는 이미 가용되었습니다.
ora-01613     쓰레드 %s는 %s 로그만을 가짐 - 가용화를 위해서는 최소 2개의 로그를 필요로 함
ora-01614     쓰레드 %s는 사용중임 - 사용가능하게할 수 없습니다.
ora-01615     쓰레드 %s는 마운트됨 - 사용불가하게할 수 없습니다.
ora-01616     쓰레드 %s는 열려 있음 - 사용불가하게할 수 없습니다.
ora-01617     마운트할 수 없음: %s는 정당한 쓰레드 번호가 아님
ora-01618     쓰레드 %s는 사용가능하지 않았음 - 마운트할 수 없습니다.
ora-01619     쓰레드 %s는 다른 인스턴스에 의해 마운트했습니다.
ora-01620     마운트에 필요한 공용 쓰레드가 없습니다.
ora-01621     데이타베이스가 열려 있으면 현 로그의 멤버를 개명할 수 없습니다.
ora-01622     쓰레드 번호가 지정되어야함 - 디폴트는 없습니다.
ora-01623     로그 %s는 쓰레드 %s에 대한 현 로그임 - 삭제할 수 없습니다.
ora-01624     로그 %s가 쓰레드 %s 복구시 필요합니다.
ora-01625     롤백 세그먼트 %s는 이 인스턴스에 속해있지 않습니다.
ora-01626     롤백 세그먼트 번호 %s는 더 이상의 트랜잭션을 처리할 수 없습니다.
ora-01627     롤백 세그먼트 번호 %s는 온라인이 아닙니다.
ora-01628     롤백 세그먼트 %s에 대한 최대 익스텐스 수 (%s)에 도달했습니다.
ora-01629     테이블 영역 %s에 대한 실행취소의 저장시 최대 익스텐트 수(%s)에 도달했음
ora-01630     테이블 영역 %s의 임시 세그먼트에 최대 익스텐트 수(%s)가 되었습니다.
ora-01631     최대 익스텐트 수(%s)에 도달 (테이블 %s.%s)
ora-01632     최대 익스텐트 수(%s)에 도달 (색인 %s.%s)
ora-01633     이 조작에는 병렬 서버 옵션이 필요합니다.
ora-01634     롤백 세그먼트 번호 %s가 오프라인 되려합니다.
ora-01635     지정된 롤백 세그먼트 번호 %s가 가용하지 않습니다.
ora-01636     롤백 세그먼트 %s가 이미 온라인 상태입니다.
ora-01637     롤백 세그먼트 %s가 다른 인스턴스(수 %s)에 의해 사용됩니다.
ora-01638     %s 파라미터는 oracle 버전 %s에서 병렬 마운트를 허용하지 않습니다.
ora-01639     데이타베이스는 잠금 프로세스 없이 병렬로 마운트할 수 없습니다.
ora-01640     활성 트랙잰션으로 테이블 공간을 읽기 전용으로 만들수 없습니다.
ora-01641     테이블스페이스 %s은 온라인이 아닙니다 - 데이타 화일을 추가할 수 없습니다.
ora-01642     읽기 전용 %s 테이블 공간에 초기 백업이 필요하지 않습니다.
ora-01643     시스템 테이블 공간를 읽기 전용으로 만들 수 없습니다.
ora-01644     %s 테이블 공간은 이미 읽기 전용입니다.
ora-01645     읽기 쓰기를 하기위해서 이전에 시도한것이 반만 완성되었습니다.
ora-01646     %s 테이블 공간은 읽기 전용입니다- 읽기 쓰기를 할 수 없습니다.
ora-01647     %s 테이블 공간은 읽기 전용이어서, 거기에 공간을 할당할 수 없습니다.
ora-01648     로그 %s는 사용불가인 쓰레드 %s의 현재 로그입니다.
ora-01649     백업 컨트롤 화일에 대한 작업이 허용되지 않습니다.
ora-01650     롤백 세그먼트 %s를 %s에 의해 %s 테이블 공간에서 확장할 수 없습니다.
ora-01651     %s로 테이블 공간 %s에 저장 취소 세그먼트를 확장할 수 없습니다.
ora-01652     %s로 테이블 공간 %s에서 임시 세그먼트를 확장할 수 없습니다.
ora-01653     테이블 %s.%s를 %s에 의해 %s 테이블 공간에서 확장할 수 없습니다.
ora-01654     색인 %s.%s를 %s에 의해 %s 테이블 공간에서 확장할 수 없습니다.
ora-01655     크러스터 %s.%s를 %s에 의해 %s 테이블 공간에서 확장할 수 없습니다.
ora-01656     최대 번호 확장 (%s)가 %s.%s 크러스터에 도달했습니다.
ora-01657     부적당한 shrink 옵션 값
ora-01658     테이블스페이스 %s에 세그먼트에 대한 initial 익스텐트를 작성할 수 없습니다.
ora-01659     테이블스페이스 %s에 %s이상의 minextents를 할당할 수 없습니다.
ora-01660     테이블스페이스 %s 은 이미 영구적인 것입니다.
ora-01661     테이블스페이스 %s 은 이미 임시적인 것입니다.
ora-01662     테이블스페이스 %s 은 비어 있지 않아 임시로 만들 수가 없습니다.
ora-01663     테이블스페이스 %s 의 내용은 항상 변경합니다.
ora-01664     정렬 세그먼트로 확장된 트랜잭션은 중지 되었습니다.
ora-01665     제어화일은 대기 제어화일이 아닙니다.
ora-01666     제어화일은 대기 제어화일을 위한 것입니다.
ora-01667     리두 로그는 대기 데이터베이스와 상반됩니다.
ora-01668     데이터 화일의 오프라인을 위해서 대기 데이터베이스가 drop 옵션을 요구합니다.
ora-01669     대기 데이터베이스 제어화일은 데이터화일과 일치하지 않습니다.
ora-01670     대기 데이터베이스 복구에 새로운 데이터화일 %s 가 필요합니다.
ora-01671     제어화일은 백업합니다, 대기 제어화일을 만들 수 없습니다.
ora-01672     제어화일에 화일이 빠졌거나 하나 더 가지고 있습니다.
ora-01673     데이터 화일 %s 은 식별된것이 아닙니다.
ora-01674     데이터 화일 %s 은 현재 화일 대신 오래된 것을 가지고 있습니다.
ora-01676     대기 화일 이름은 %s의 변환을 하는데 최대 %s의 길이를 초과했습니다.
ora-01677     대기 화일 이름이 파라미터 변환을 다른 인스턴스와 다르게 했습니다.
ora-01678     파라미터 %s 은 패턴과 교체로 된 두가지 스트링을 가지고 있어야 합니다.
ora-01679     데이터베이스는 exclusive로 마운트 되어야 하고 열려 있지 않아야 합니다.
ora-01680     만약 gc_files_to_locks이 사용하고 있으면 gc_db_locks가 영일 수 없습니다.
ora-01700     리스트 내의 사용자명이 중복되었습니다.
ora-01701     클러스터가 부적합합니다.
ora-01702     뷰는 부적합합니다.
ora-01703     키워드 synonym이 없습니다.
ora-01704     스트링이 너무 깁니다.
ora-01705     상관 열에는 외부 결합을 지정할 수 없습니다.
ora-01706     사용자 함수의 결과가 너무 큽니다.
ora-01707     키워드 list가 없습니다.
ora-01708     access 또는 session을 지정해 주십시오
ora-01709     프로그램이 존재하지 않습니다.
ora-01710     키워드 of가 없습니다.
ora-01711     중복된 권한이 리스트되어 있습니다.
ora-01712     자신이 소유하지 않은 권한을 허가할 수 없습니다.
ora-01713     그 권한에 대해서는 grant option 이 존재하지 않습니다.
ora-01714     사용자 함수의 실행중 오류가 발생했습니다.
ora-01715     클러스터 색인에는 unique를 사용할 수 없습니다.
ora-01716     클러스터 색인에는 nosort를 사용할 수 없습니다.
ora-01717     secta : 액세스 모드 토큰이 부적합합니다.
ora-01718     by access | session절은 noaudit에 대해서는 허용되지 않습니다.
ora-01719     외부 결합 운영 (+)는 or 또는 in의 연산수를 허용하지 않습니다.
ora-01720     %s에 대한 허가(grant) 옵션은 존재하지 않습니다.
ora-01721     트랜잭션에서 userenv(commitscn)을 2회 이상 불렀습니다.
ora-01722     수치가 부적합합니다.
ora-01723     길이가 0인 열은 지정할 수 없습니다.
ora-01724     부동 소숫점 수치의 정도를 벗어났습니다 (1 to 126)
ora-01725     userenv(commitscn)는 여기에서 허용되지 않습니다.
ora-01726     테이블의 지정이 부적합합니다.
ora-01727     수치의 정도 범위(38 자리 이내)를 초과했습니다.
ora-01728     수치의 스케일 범위(-84 에서 127)를 초과했습니다.
ora-01729     데이타베이스 링크명을 지정해 주십시오
ora-01730     지정한 열명의 수가 부적합합니다.
ora-01731     뷰 정의가 부적합(순환)합니다.
ora-01732     뷰에 대한 데이타 조작이 부적합합니다.
ora-01733     가상 열은 사용할 수 없습니다.
ora-01734     잘못된 파라미터 - extent min 값이 extent max 보다 큽니다.
ora-01735     부적합한 alter table 옵션입니다.
ora-01736     [not] successful 을 지정해 주십시오.
ora-01737     공유, 배타 모드에서만 테이블을 잠금할 수 있습니다.
ora-01738     키워드 in 을 지정해 주십시오
ora-01739     키워드 mode 를 지정해 주십시오
ora-01740     이중 인용부를 지정해 주십시오
ora-01741     길이가 0인 식별자는 부적합합니다.
ora-01742     주석이 정확하게 종료되지 않았습니다.
ora-01743     내부적 불일치 : 사용자 함수 색인이 부적합합니다.
ora-01744     into구의 지정이 부적합합니다.
ora-01745     호스트/바인드 변수명이 부적합합니다.
ora-01746     인디케이터 변수는 사용할 수 없습니다.
ora-01747     열명을 올바르게 지정해 주십시오.
ora-01748     열명 그 자체만 사용할 수 있습니다.
ora-01749     자신의 권한으로는 grant/revoke 할 수 없습니다.
ora-01750     update/reference 는 열에 의해서가 아닌 테이블 전체로부터 revoke 될 수 있습니다.
ora-01751     부적당한 덤프 취소 옵션입니다.
ora-01752     뷰으로 부터 정확하게 하나의 키-보전된 테이블 없이 삭제할 수 없습니다.
ora-01753     열 정의가 클러스터 열의 정의와 일치하지 않습니다.
ora-01754     long 유형의 열은 테이블에 1 개만 포함될 수 있습니다.
ora-01755     영역 수나 블록 수를 지정해야만 합니다.
ora-01756     단일 인용부를 지정해 주십시오
ora-01757     개체 수를 지정해야 합니다.
ora-01758     not null 열을 추가하기 위해서는 테이블이 비어 있어야 합니다.
ora-01759     사용자 함수가 올바르게 정의되지 않았습니다.
ora-01760     함수의 인수가 부적합합니다.
ora-01761     결합문는 유일 테이블에 dml 작업으로 맵 할 수 없습니다.
ora-01762     vopdrv: 뷰의 질의 블록이 from 구에 없습니다.
ora-01763     갱신 또는 삭제가 외부 결합 테이블을 포함하고 있습니다.
ora-01764     결합의 새로운 갱신 값은 유일한것을 보증할 수 없습니다.
ora-01765     테이블의 소유자명을 지정할 수 없습니다.
ora-01766     데이타 사전 개체명을 사용할 수 없습니다.
ora-01767     update ... set 식은 부속 질의이어야 합니다.
ora-01768     수치 열이 너무 깁니다.
ora-01769     cluster 옵션 지정이 중복되었습니다.
ora-01770     cluster 옵션은 사용할 수 없습니다.
ora-01771     클러스터 테이블에 대한 옵션이 부적합합니다.
ora-01772     level에 대한 값을 지정해야 합니다.
ora-01773     지정한 create table 문에는 열 데이타 유형을 지정할 수 없습니다.
ora-01774     한번 이상 덤프 취소 옵션이 지정되었습니다.
ora-01775     동의어가 순환 고리 유형으로 정의되어 있습니다.
ora-01776     결합 뷰에 의하여 하나 이상의 기본 테이블을 수정할 수 없습니다.
ora-01777     with grant 옵션은 사용할 수 없습니다.
ora-01778     부속 질의의 내포 레벨의 제한을 초과했습니다.
ora-01779     키-보존된것이 아닌 테이블로 맵한 열을 수정할 수 없습니다.
ora-01780     스트링 상수가 필요합니다.
ora-01781     unrecoverable은 as select와 함께 지정해야 합니다.
ora-01782     클러스터 또는 클러스터 테이블에 대해서는 unrecoverable을 지정할 수 없습니다.
ora-01783     recoverable 또는 unrecoverable 중 하나만을 지정할 수 있습니다.
ora-01784     데이타베이스 미디어 복구가 사용불가이면 recoverable을 지정할 수 없습니다.
ora-01785     order by 항목은 select 리스트 식의 수라야 합니다.
ora-01786     for update 구는 사용할 수 없습니다.
ora-01787     질의 블록당 1개의 구만 허용됩니다.
ora-01788     connect by 구를 지정해 주십시오.
ora-01789     질의의 결과 열의 수가 틀립니다.
ora-01790     대응하는 식과 같은 데이타 유형이어야 합니다.
ora-01791     select 식이 부적합합니다.
ora-01792     테이블, 뷰에 지정 가능한 열의 최대수는 254 입니다.
ora-01793     지정 가능한 색인 열의 최대수는 16 입니다.
ora-01794     지정 가능한 클러스터 열의 최대수는 16 입니다.
ora-01795     리스트에 지정 가능한 식의 최대수는 254 입니다.
ora-01796     연산자의 지정이 부적합합니다.
ora-01797     연산자의 뒤에 any 또는 all을 지정해 주십시오.
ora-01798     exception 키워드가 누락되었습니다.
ora-01799     열은 부속 질의에 외부결합될 수 없습니다.
ora-01800     날짜 형식 내의 리터럴이 너무 길어서 처리할 수 없습니다.
ora-01801     날짜 형식이 내부 버퍼에 비해 너무 깁니다.
ora-01802     율리우스일의 지정이 범위를 초과했습니다.
ora-01803     날짜/시각의 획득 실패
ora-01810     형식 코드가 2 번 나타났습니다.
ora-01811     율리우스일에서 년간 통산일의 사용은 금지되어 있습니다.
ora-01812     년은 1 번만 지정할 수 있습니다.
ora-01813     시간은 1 번만 지정할 수 있습니다.
ora-01814     am/pm 과 a.m./p.m.은 혼재할 수 없습니다.
ora-01815     bc/ad 와 b.c./a.d.는 혼재할 수 없습니다.
ora-01816     월은 1 번만 지정할 수 있습니다.
ora-01817     요일은 1 번만 지정할 수 있습니다.
ora-01818     hh24와 am/pm은 혼재할 수 없습니다.
ora-01819     부호가 붙은 년과 bc/ad는 혼재할 수 없습니다.
ora-01820     날짜 지정에 포함된 형식 코드가 부적합합니다.
ora-01821     날짜 형식이 부적합합니다.
ora-01830     날짜 형식의 지정에 불필요한 데이타가 포함되어 있습니다.
ora-01831     년과 율리우스일은 혼재할 수 없습니다.
ora-01832     년의 일과 율리우스일은 혼재할 수 없습니다.
ora-01833     월과 율리우스일은 혼재할 수 없습니다.
ora-01834     월의 일과 율리우스일은 혼재할 수 없습니다.
ora-01835     요일과 율리우스일은 혼재할 수 없습니다.
ora-01836     시와 일의 초는 혼재할 수 없습니다.
ora-01837     시의 분과 일의 초는 혼재할 수 없습니다.
ora-01838     분의 초와 일의 초는 혼재할 수 없습니다.
ora-01839     지정된 월에 대한 날짜가 부적합합니다.
ora-01840     입력된 값의 길이가 날짜 형식에 비해 부족합니다.
ora-01841     년은 -4713 과 +4713 사이의 값으로 지정해 주십시오.
ora-01842     분기는 1 부터 4 사이의 값을 지정해 주십시오.
ora-01843     지정한 월이 부적합합니다.
ora-01844     주를 올바르게 지정해 주십시오 ( 1 에서 52 사이 )
ora-01845     주를 올바르게 지정해 주십시오 ( 1 에서 5 사이 )
ora-01846     지정한 요일이 부적합합니다.
ora-01847     날짜를 올바르게 지정해 주십시오 ( 1 에서 말일까지 )
ora-01848     날짜를 올바르게 지정해 주십시오 ( 1 에서 365 사이 )
ora-01849     시간을 올바르게 지정해 주십시오 ( 1 에서 12 사이 )
ora-01850     시간을 올바르게 지정해 주십시오 ( 0 에서 23 사이 )
ora-01851     분을 올바르게 지정해 주십시오 ( 0 에서 59 사이 )
ora-01852     초를 올바르게 지정해 주십시오 ( 0 에서 59 사이 )
ora-01853     초를 올바르게 지정해 주십시오 ( 0 에서 86399 사이 )
ora-01854     율리우스 날짜는 1에서 5373484 사이여야 합니다.
ora-01855     am/a.m. 또는 pm/p.m.이 필요합니다.
ora-01856     bc/b.c. 또는 ad/a.d.이 필요합니다.
ora-01857     시간대가 부적합합니다.
ora-01858     수치를 지정해야할 곳에 비수치 문자가 지정되었습니다.
ora-01859     문자를 지정해야할 곳에 비문자가 지정되었습니다.
ora-01860     년의 주는 1 에서 53 사이이어야 합니다.
ora-01861     스트링이 형식 스트링에 맞지 않습니다.
ora-01862     이 형식의 항목에 대한 잘못된 자리수
ora-01898     precision 지정자가 너무 많습니다.
ora-01899     잘못된 precision 지정자입니다.
ora-01900     키워드 logfile을 지정해 주십시오
ora-01901     키워드 rollback을 지정해 주십시오
ora-01902     키워드 segment를 지정해 주십시오
ora-01903     키워드 events를 지정해 주십시오
ora-01904     키워드 datafile을 지정해 주십시오
ora-01905     키워드 storage를 지정해 주십시오
ora-01906     키워드 backup을 지정해 주십시오
ora-01907     키워드 tablespace를 지정해 주십시오
ora-01908     키워드 exists를 지정해 주십시오
ora-01909     키워드 reuse를 지정해 주십시오
ora-01910     키워드 tables을 지정해 주십시오
ora-01911     키워드 contents를 지정해 주십시오
ora-01912     키워드 row를 지정해 주십시오
ora-01913     키워드 exclusive를 지정해 주십시오
ora-01914     시퀀스 번호에 대한 감사 옵션이 부적합합니다.
ora-01915     뷰에 대한 감사 옵션이 부적합합니다.
ora-01916     키워드 online, offline, resize, autoextend 또는 end를 지정하십시오
ora-01917     사용자 또는 롤 %s가 존재하지 않습니다.
ora-01918     사용자 %s가 존재하지 않습니다.
ora-01919     롤 %s가 존재하지 않습니다.
ora-01920     사용자명 %s가 다른 사용자나 롤명과 상충됩니다.
ora-01921     롤명 %s가 다른 사용자나 롤명과 상충됩니다.
ora-01922     %s를 삭제하려면 cascade를 지정하여야 합니다.
ora-01923     개체가 다른 사용자에 의해서 잠금 되어 cascade가 비정상 종료되었습니다.
ora-01924     롤 %s가 허가되지 않았거나 존재하지 않습니다.
ora-01925     가용 롤의 최대치 %s를 초과했습니다.
ora-01926     with grant option으로 롤을 grant할 수 없습니다.
ora-01927     허가하지 않은 권한을 revoke할 수 없습니다.
ora-01928     모든 권한에 대하여 grant 옵션이 허가되지는 않았습니다.
ora-01929     grant할 권한이 없습니다.
ora-01931     %s를 롤에게 허가할 수 없습니다.
ora-01932     롤 %s에 대한 admin 옵션이 허가되지 않았습니다.
ora-01933     롤에 대한 권한으로 저장 개체를 생성할 수 없습니다.
ora-01934     순환되는 롤 권한 부여가 감지되었습니다.
ora-01935     누락된 사용자 혹은 롤명
ora-01936     사용자나 롤을 생성시 소유자를 지정할 수 없습니다.
ora-01937     부적절한 롤명
ora-01938     create user에 대한 identified by가 지정되어야 합니다.
ora-01939     admin option만이 지정될 수 있습니다.
ora-01940     현재 연결되어 있는 사용자를 삭제할 수 없습니다.
ora-01941     키워드 sequence가 요구됩니다.
ora-01942     identified by 와 externally는 모두 지정될 수 없습니다.
ora-01943     identified by가 이미 지정되었습니다.
ora-01944     identified externally가 이미 지정되었습니다.
ora-01945     default role[s]가 이미 지정되었습니다.
ora-01946     default tablespace가 이미 지정되었습니다.
ora-01947     temporary tablespace가 이미 지정되었습니다.
ora-01949     role 키워드가 요구합니다.
ora-01950     테이블 영역 %s에 대한 권한이 없읍
ora-01951     role %s가 %s에 허가되지 않았습니다.
ora-01952     시스템 권한이 %s에 허가되지 않았습니다.
ora-01953     명령어가 더 이상 유효하지 않음,alter user를 보내십시오
ora-01954     create user에 default role절이 유효하지 않습니다.
ora-01955     default role %s가 사용자에게 허가되지 않았습니다.
ora-01956     os_roles이 사용될시 부적절한 명령어
ora-01957     키워드 min 혹은 max 를 지정해 주십시오
ora-01958     layer 옵션을 위한 정수가 필요합니다.
ora-01959     opcode 옵션을 위한 정수가 필요합니다.
ora-01960     부적절한 덤프 로그 화일 옵션입니다.
ora-01961     부적절한 덤프 옵션입니다.
ora-01962     화일 번호 혹은 시퀀스 번호를 지정해야 합니다.
ora-01963     블록 번호를 지정해야 합니다.
ora-01964     time 옵션을 위한 시간을 지정해야 합니다.
ora-01965     period 를 지정해야 합니다.
ora-01967     create controlfile 의 부적절한 옵션입니다.
ora-01968     resetlogs 혹은 noresetlogs 를 한번만 지정하십시오
ora-01969     resetlogs 혹은 noresetlogs 를 지정해야 합니다.
ora-01970     create controlfile에 대한 데이타베이스 명을 지정해야 합니다.
ora-01971     부적절한 alter tracing 옵션
ora-01972     alter tracing enable 혹은 disable에 대한 스트링을 지정해야 합니다.
ora-01973     변경 번호 누락
ora-01974     부적절한 아카이브옵션
ora-01975     변환 번호 %s에 부적절한 문자
ora-01976     변경 번호 누락
ora-01977     쓰레드 번호 누락
ora-01978     시퀀스 번호 누락
ora-01979     롤 %s에 대한 암호가 틀리거나 누락되었습니다.
ora-01980     os role 초기화시 오류
ora-01981     현 권한취소를 수행하려면 cascade constraints가 지정되어야 합니다.
ora-01982     테이블에 대한 부적절한 감사 옵션
ora-01983     default에 대한 부적절한 감사 옵션
ora-01984     프로시저/패캐지/함수에 대한 부적절한 감사 옵션
ora-01985     license_max_users 파라미터가 초과되어 사용자를 생성할 수 없습니다.
ora-01986     optimizer_goal에 대한 옵션 부적합
ora-01987     클라이언트 os 사용자명이 너무 깁니다.
ora-01988     원격 os 로그온이 허용되지 않습니다.
ora-01989     롤 %s는 운영 시스템에 의해 권한되지 않았습니다.
ora-01990     암호 %s 화일을 여는데 오류가 발생했습니다.
ora-01991     %s 암호 화일이 부적합합니다.
ora-01992     %s 암호 화일을 닫는데 오류가 발생했습니다.
ora-01993     %s 암호 화일을 쓰는 중에 오류가 발생했습니다.
ora-01994     grant 실패: 공용 암호 화일에다 사용자를 추가할 수 없습니다.
ora-01995     %s 암호 화일을 읽는 중에 오류가 발생했습니다.
ora-01996     grant 실패: %s 암호 화일이 꽉 찼습니다.
ora-01997     grant 실패: %s 사용자는 여기에 없습니다.
ora-01998     revoke 실패: sys 사용자는 항상 sysoper 와 sysdba를 가지고 있습니다.
ora-01999     암호 화일 모드는 %s 에서 %s로 바꾸었습니다.
ora-02000     누락된 %s 키워드
ora-02001     사용자 sys는 빈리스트 그룹와 함께 색인을 생성하는것을 허락하지 않습니다.
ora-02002     감사 추적 테이블에 기록 중 오류가 발생했습니다.
ora-02003     userenv 파라미터가 부적합합니다.
ora-02004     보안 위반
ora-02005     길이(-1)가 부적합합니다.
ora-02006     팩형 10진 형식 스트링이 부적합합니다.
ora-02007     allocate 또는 deallocate 옵션을 rebuild와 같이 사용할 수 없습니다.
ora-02008     숫자가 아닌 열에 대하여 0 이외의 스케일이 지정되었습니다.
ora-02009     화일에 지정된 크기는 0이 아니어야 합니다.
ora-02010     호스트 연결 스트링을 지정해 주십시오
ora-02011     데이타베이스 링크명이 중복되었습니다.
ora-02012     키워드 using 을 지정해 주십시오
ora-02013     키워드 connect 를 지정해 주십시오
ora-02014     for update 구를 사용해서 선택할 수 없습니다.
ora-02015     원격 테이블에 대하여 for update 구는 사용할 수 없습니다.
ora-02016     원격 데이타베이스에서는 start with 로 부속 질의를 사용할 수 없습니다.
ora-02017     정수 값을 지정해 주십시오
ora-02018     같은 이름의 데이타베이스 링크가 개방, 연결되어 있습니다.
ora-02019     원격 데이타베이스를 찾을 수 없을때 기술적으로 연결하십시오
ora-02020     너무 많은 데이타베이스 링크들이 사용되고 있습니다.
ora-02021     원격 데이타베이스에 ddl 조작들이 허용되지 않습니다.
ora-02022     원격 문장이 원격 개체를 갖는 최적화 되지않을 뷰를 사용합니다.
ora-02023     원격 데이타베이스는 start with, connect by 술어를 평가할 수 없습니다.
ora-02024     데이타 링크를 찾을 수 없습니다.
ora-02025     sql 문장에 있는 모든 테이블은 원격 데이타베이스에 있어야만 합니다.
ora-02026     키워드 link 를 지정해 주십시오
ora-02027     long 열은 복수 행의 갱신이 불가능합니다.
ora-02028     정확한 행의 번호를 인출 하는것이 지원되지 않습니다.
ora-02029     키워드 file 을 지정해 주십시오
ora-02030     고정 테이블/고정 뷰에서는 선택만 가능합니다.
ora-02031     고정 테이블에 대하여 rowid 를 지정할 수 없습니다.
ora-02032     클러스터 색인의 작성 이전에 클러스터 테이블을 사용할 수 없습니다.
ora-02033     이미 클러스터 색인이 존재하고 있습니다.
ora-02034     스피드 바인드가 허용되지 않습니다.
ora-02035     부당한 작업묶음의 조합입니다.
ora-02036     자동커서 개방시 묘사할 변수가 너무 많습니다.
ora-02037     초기화되지 않은 스피드 바인드 영역
ora-02038     배열 유형에 정의가 허용되지 않습니다
ora-02039     배열 유형에 값으로 바인드는 허용되지 않습니다
ora-02040     원격 데이타베이스는 %s는 두단계 커밋을 지원하지 않습니다.
ora-02041     클라이언트 데이타베이스는 트랜잭션을 시작하지 않습니다.
ora-02042     너무 많은 분산 트랜잭션들
ora-02043     %s를 실행하기 전에 현재 트랜잭션을 끝내야 합니다.
ora-02044     트랜잭션 관리자 로그인이 거부되었음: 트랜잭션이 진행중입니다.
ora-02045     글로벌 트랜잭션에 관여한 로컬 세션이 너무 많습니다.
ora-02046     분산 트랜잭션이 이미 시작되었습니다.
ora-02047     진행 중에 분산 트랜잭션을 결합할 수 없습니다.
ora-02048     로그잉하지 않고 분산 트랜잭션을 시작하려 했습니다.
ora-02049     시간초과: 분산 트랜잭션이 잠금으로 대기중 입니다.
ora-02050     트랜잭션 %s가 롤백되고, 다른 원격 db는 불명료한 상태입니다.
ora-02051     동일 트랜잭션내에 다른 세션이 실패했습다.
ora-02052     원격 트랜잭션이 %s에서 실패했습니다.
ora-02053     트랜잭션 %s가 커밋되고, 다른 원격 db는 불명료한 상태입니다.
ora-02054     트랜잭션 %s이 불명료한 상태입니다.
ora-02055     분산 수정 작업이 실패했음; 롤백이 요구됩니다.
ora-02056     2pc: %s: 잘못된 두 단계 명령어 번호 %s(%s로 부터의)
ora-02057     2pc: %s: 잘못된 두 단계 복구상태 번호 %s(%s로 부터의)
ora-02058     id %s를 가지는 준비된 트랜잭션이 없습니다.
ora-02059     커밋 코맨트의 ora-2pc-crash-test-%s
ora-02060     select for update문에 분산 테이블에 대한 결합이 지정되었습니다.
ora-02061     select for update에 분산 테이블 목록이 지정되었습니다.
ora-02062     분산 복구가 dbid %s를 받았습니다(%s가 기대되었으나)
ora-02063     %s%s가 선행됨 (%s%s로 부터)
ora-02064     분산 작업이 지원되지 않습니다.
ora-02065     alter system에 대한 부당한 옵션
ora-02066     누락 혹은 부당한 mts_dispatchers 텍스트
ora-02067     트랜잭션 혹은 세이브포인트 롤백이 요구됩니다.
ora-02068     %s%s로 부터의 다음의 치명적인 오류가 있습니다.
ora-02069     global_names 파라미터는 이 작업에 true라고 설정해야만 합니다.
ora-02070     데이타베이스 %s%s는 이문맥에서 %s를 지원하지 않습니다.
ora-02071     원격 데이타베이스 %s에 대한 능력을 초기화시 오류
ora-02072     분산 데이타베이스의 네트워크 프로토콜이서로 맞지 않습니다.
ora-02073     원격 수정에서는 시퀀스번호가 지원되지 않습니다.
ora-02074     분산 트랜잭션에 %s을 할 수 없습니다.
ora-02075     사용되지 않는 오류입니다.
ora-02076     수정된 테이블이나 long 열의 시퀀스가 동일한 노드에 있어야 합니다.
ora-02077     select문에서 long 열의 값을 가지고 올때는 동일한 노드에 있어야 합니다.
ora-02078     alter system fixed_date에 대한 지정이 잘못됐습니다.
ora-02079     새로운 세션이 분산 트랜잭션의 커밋에 동참할 수 있습니다.
ora-02080     데이타베이스 링크가 사용중입니다.
ora-02081     데이타베이스 링크가 열려있지 않았습니다.
ora-02082     루프백(loopback) 데이타베이스 링크는 연결 수식어를 가져야합니다.
ora-02083     데이타베이스명에 부적절한 문자 %s가 있습니다.
ora-02084     데이타베이스명에 요소가 누락되었습니다.
ora-02085     데이타베이스 링크 %s가 %s에 연결됩니다.
ora-02086     데이타베이스 (링크)명이 너무깁니다.
ora-02087     동일 트랜잭션내의 다른 프로세스에 의해 개체가 잠금 되었습니다.
ora-02088     분산 데이타베이스 옵션이 설치되지 않았습니다.
ora-02089     종속 세션에서는 commit이 허용되지 않습니다.
ora-02090     네트워크 오류: callback+passthru
ora-02091     트랜잭션이 롤백되었습니다.
ora-02092     분산 트랜잭션에 대한 트랜잭션 테이블 슬롯이 부족합니다.
ora-02093     transactions_per_rollback_segment(%s)가 가능한 최대치(%s) 보다 많습니다.
ora-02094     중복 옵션이 설치되지 않았습니다.
ora-02095     지정된 초기화 파라미터를 수정할 수 없습니다.
ora-02096     지정된 초기화 파라미터는 이 옵션으로 수정가능하지 않습니다.
ora-02098     색인-테이블 참조 (:i)를 파싱하는데 오류
ora-02099     내부 목적으로 사용됨, 출력되지 않아야 합니다.
ora-02100     pcc: 메모리 부족 (할당할 수 없습니다.
ora-02101     pcc: 일치하지 않는 커서 캐쉬(uce/cuc 불일치)
ora-02102     pcc: 일치하지 않는 커서 캐쉬(이 uce에 대한 cuc 엔트리가 없습니다.
ora-02103     pcc: 일치하지 않는 커서 캐쉬(cuc 참조가 범위를 벗어남)
ora-02104     pcc: 일치하지 않는 호스트 캐쉬(사용가능한 cuc가 없습니다)
ora-02105     pcc: 일치하지 않는 커서 캐쉬(캐쉬내에 cuc 엔트리가 없습니다)
ora-02106     pcc: 일치하지 않는 커서 캐쉬(oracursor nr이 잘못됐습니다)
ora-02107     pcc: 프로그램이 수행시 라이브러리에 대해 너무 오래됨: 다시 pcc하십시오
ora-02108     pcc: 수행시 라이브러리에 유효하지않은 디스크립터가 넘겨졌습니다.
ora-02109     pcc: 일치하지 않는 호스트 캐쉬(sit 참조가 범위를 벗어남)
ora-02110     pcc: 일치하지 않는 호스트 캐쉬(유효하지 않은 sqi 유형)
ora-02111     pcc: 힙 일관성 오류
ora-02112     pcc: select..into가 너무 많은 행을 리턴합니다.
ora-02140     테이블스페이스 이름이 부적합합니다.
ora-02141     offline 옵션이 부적합합니다.
ora-02142     적절한 alter tablespace 옵션을 지정해 주십시오
ora-02143     storage 옵션이 부적합합니다.
ora-02144     적절한 alter cluster 옵션을 지정해 주십시오
ora-02145     storage 옵션을 지정해 주십시오
ora-02146     shared 옵션이 복수 회 지정되었습니다.
ora-02147     shared 와 exclusive 는 혼용할 수 없습니다.
ora-02148     exclusive 옵션이 복수 회 지정되었습니다.
ora-02155     default 테이블 영역 식별자가 부적합합니다.
ora-02156     temporary의 테이블 영역 식별자가 부적합합니다.
ora-02157     alter user 옵션을 지정해 주십시오
ora-02158     create index 옵션이 부적합합니다.
ora-02159     설치된 dlm은 릴리즈가능한 잠금 모드를 지원하지 않습니다.
ora-02161     maxlogfiles에 대한 값이 부적합합니다.
ora-02162     maxdatafiles에 대한 값이 부적합합니다.
ora-02163     freelist groups에 대한 값이 부적합합니다.
ora-02164     datafile 구가 2개 이상 지정되었습니다.
ora-02165     create database 옵션의 지정이 부적합합니다.
ora-02166     archivelog 와 noarchivelog 가 함께 지정되었습니다.
ora-02167     logfile 구가 2 회 이상 지정되었습니다.
ora-02168     freelists에 대한 부당한 값
ora-02169     freelists 저장영역 옵션은 허용되지 않습니다.
ora-02170     freelist groups 저장영역 옵션은 허용되지 않습니다.
ora-02171     maxloghistory에 대한 부당한 값
ora-02172     사용불가 쓰레드에 대한 public 키워드는 적합하지 않습니다.
ora-02173     drop tablespace 옵션이 부적합합니다.
ora-02174     요구되는 쓰레드 번호의 누락
ora-02175     롤백 세그먼트 명이 부적합합니다.
ora-02176     create rollback segment 옵션이 부적합합니다.
ora-02177     요구되는 그룹 번호의 누락
ora-02178     올바른 구문 : set transaction read { only | write }
ora-02179     적당한 옵션: isolation level { serializable | read committed }
ora-02180     create tablespace 옵션이 부적합합니다.
ora-02181     rollback work 옵션이 부적합합니다.
ora-02182     세이브포인트명을 지정해 주십시오
ora-02183     적당한 옵션: isolation_level { serializable | read committed }
ora-02184     revoke 에서는 자원의 할당량을 지정할 수 없습니다.
ora-02185     commit 뒤에 work 이외의 토큰이 지정되었습니다.
ora-02186     테이블 영역의 자원 권한은 다른 권한과 동시에 지정할 수 없습니다.
ora-02187     할당량의 지정이 부적합합니다.
ora-02189     on <tablespace> 가 필요합니다.
ora-02190     키워드 tables를 지정해 주십시오
ora-02191     올바른 구문: set transaction use rollback segment <rbs>
ora-02192     pctincrease는 롤백 세그먼트 영역절에서는 허용되지 않습니다.
ora-02194     이벤트 지정 구문 오류 %s (중요치 않은 오류 %s), %s 부근에
ora-02195     %s 개체를 %s 테이블스페이스에서 만들도록 시도합니다.
ora-02196     permanent/temporary 옵션이 이미 지정되었습니다.
ora-02197     화일 리스트가 이미 지정되어 있습니다.
ora-02198     online/offline 옵션이 이미 지정되어 있습니다.
ora-02199     datafile 구를 지정해 주십시오
ora-02200     with grant option 은 public 에 대하여 사용할 수 없습니다.
ora-02201     시퀀스를 사용할 수 없습니다.
ora-02202     클러스터에서는 더이상의 테이블을 작성할 수 없습니다.
ora-02203     initial 영역 옵션은 허가되지 않습니다.
ora-02204     alter, index, references 그리고 execute는 뷰에서 사용할 수 없습니다.
ora-02205     select 와 alter 권한만이 시퀀스에 대하여 사용할 수 있습니다.
ora-02206     initrans 옵션 지정이 중복되었습니다.
ora-02207     initrans 옵션의 값이 부적합합니다.
ora-02208     maxtrans 옵션 지정이 중복되었습니다.
ora-02209     maxtrans 옵션의 값이 부적합합니다.
ora-02210     alter table 옵션을 지정해 주십시오
ora-02211     pctfree 또는 pctused 에 대한 값이 부적합합니다.
ora-02212     pctfree 옵션 지정이 중복되었습니다.
ora-02213     pctused 옵션 지정이 중복되었습니다.
ora-02214     backup 옵션 지정이 중복되었습니다.
ora-02215     tablespace 구가 중복되었습니다.
ora-02216     테이블 영역명을 지정해 주십시오
ora-02217     기억 영역(storage) 옵션 지정이 중복되었습니다.
ora-02218     initial 옵션의 값이 부적합합니다.
ora-02219     next 옵션의 값이 부적합합니다.
ora-02220     minextents 옵션의 값이 부적합합니다.
ora-02221     maxextents 옵션의 값이 부적합합니다.
ora-02222     pctincrease 옵션의 값이 부적합합니다.
ora-02223     부당한 optimal 저장 영역 옵션값
ora-02224     execute 권한은 테이블에 대해서는 허용되지 않습니다.
ora-02225     프로시저에 대해서는 execute 권한만이 유효합니다.
ora-02226     부당한 maxextents값 (허용 최대치: %s)
ora-02227     클러스터명이 부적합합니다.
ora-02228     size 지정이 중복되었습니다.
ora-02229     size 옵션의 값이 부적합합니다.
ora-02230     alter cluster 옵션이 부적합합니다.
ora-02231     적절한 alter database 옵션을 지정해 주십시오
ora-02232     mount 모드가 부적합합니다.
ora-02233     close 모드가 부적합합니다.
ora-02234     이 테이블에 대한 변경은 이미 로그되어 있습니다.
ora-02235     이 테이블은 다른 테이블에 이미 변경을 기록했습니다.
ora-02236     화일명이 부적합합니다.
ora-02237     화일 크기가 부적합합니다.
ora-02238     화일명 리스트의 화일 수가 다릅니다.
ora-02239     이 시퀀스를 참조하는 개체가 있습니다.
ora-02240     objno 혹은 tabno에 대한 부당한 값
ora-02241     extents (file <n> block <n> size <n>, ...)유형이어야 합니다.
ora-02242     alter index 옵션을 지정해 주십시오
ora-02243     alter index 또는 alter snapshot 옵션이 부적합합니다.
ora-02244     alter rollback segment 옵션이 부적합합니다.
ora-02245     롤백 세그먼트 명이 부적합합니다.
ora-02246     events 의 텍스트를 지정해 주십시오
ora-02247     alter session 옵션을 지정해 주십시오
ora-02248     alter session 옵션이 부적합합니다.
ora-02249     maxlogmembers에 값이 빠졌거나 부당한 값입니다.
ora-02250     적절한 제약명을 지정해 주십시오
ora-02251     부속 질의는 사용할 수 없습니다.
ora-02252     검사 제약 조건이 올바르지 않습니다.
ora-02253     제약을 지정할 수 없습니다.
ora-02254     default <expression>은 사용할 수 없습니다.
ora-02255     못쓰게된 7.1.5
ora-02256     참조하고 있는 열의 숫자, 유형 그리고 크기는 참조 열의 수와 일치해야 합니다.
ora-02257     열의 최대수를 초과했습니다.
ora-02258     null, not null 지정이 중복 또는 혼재되었습니다.
ora-02259     unique/primary key의 지정이 중복되었습니다.
ora-02260     테이블에는 기본 키를 1 개만 포함시킬 수 있습니다.
ora-02261     유일 키 또는 기본 키가 이미 존재하고 있습니다.
ora-02262     ora-%05d 발생. 열의 디폴트 값 식의 유형 검사 오류.
ora-02263     열의 데이타 유형을 지정해 주십시오
ora-02264     기존의 제약에 사용된 이름입니다.
ora-02265     참조 열의 데이타 유형이 정의되지 않았습니다.
ora-02266     외래 키에 의해 참조되는 유일/기본 키가 테이블에 있습니다.
ora-02267     열의 데이타 유형이 참조 열의 데이타 유형와 일치하지 않습니다.
ora-02268     참조 테이블에 기본 키가 없습니다.
ora-02269     키 열은 long 데이타 유형을 취할 수 없습니다.
ora-02270     이 열목록에 대한 유일 혹은 일차 키가 일치하지 않습니다.
ora-02271     제약명이 없습니다.
ora-02272     제약 열은 long 데이타 유형을 취할 수 없습니다.
ora-02273     유일/기본 키가 외부 키에 의해 참조되었습니다.
ora-02274     중복된 참조 제약 지정입니다.
ora-02275     참조 제약이 이미 테이블에 존재합니다.
ora-02276     디폴트 유형이 열의 유형과 일치하지 않습니다.
ora-02277     시퀀스명이 부적합합니다.
ora-02278     maxvalue/nomaxvalue 지정이 중복 또는 혼재되어 있습니다.
ora-02279     minvalue/nominvalue 지정이 중복 또는 혼재되어 있습니다.
ora-02280     cycle/nocycle 지정이 중복 또는 혼재되어 있습니다.
ora-02281     cache/nocache 지정이 중복 또는 혼재되어 있습니다.
ora-02282     order/noorder 지정이 중복 또는 혼재되어 있습니다.
ora-02283     개시 시퀀스 번호는 변경할 수 없습니다.
ora-02284     increment by 지정이 중복되었습니다.
ora-02285     start with 지정이 중복되었습니다.
ora-02286     alter sequence 옵션을 지정해 주십시오
ora-02287     시퀀스 번호는 이 위치에 사용할 수 없습니다.
ora-02288     open 모드가 부적합합니다.
ora-02289     시퀀스가 존재하지 않습니다.
ora-02290     체크 제약조건(%s.%s)이 위배되었습니다.
ora-02291     무결성 제약조건(%s.%s)이 위배되었습니다- 부모 키가 없습니다.
ora-02292     무결성 제약조건(%s.%s)이 위배되었습니다- 자식 레코드가 발견되었습니다.
ora-02293     (%s.%s)를 사용가능하게 할 수 없습니다 - 잘못된 제약을 점검
ora-02294     참조 제약을 추가할 수 없음 - 부모 키가 없습니다.
ora-02295     제약에 대한 하나 이상의 사용가능/사용불가 절이 있습니다.
ora-02296     제약 (%s.%s)을 사용가능하게 할 수 없음 - 부합하는 값이 없습니다.
ora-02297     제약 (%s.%s)을 사용불가하게 할 수 없음 - 종속관계가 있습니다.
ora-02298     제약 (%s.%s)을 사용가능하게 할 수 없음 - 부모 키가 없습니다.
ora-02299     제약 (%s.%s)을 사용가능하게 할 수 없음 - 중복 키가 있습니다.
ora-02351     레코드 %s: 거부되었습니다- 테이블 %s, 열 %s에서 오류
ora-02352     직접 패스 연결은 동기종 간에만 가능합니다.
ora-02353     복수 자리의 문자 오류
ora-02354     필드 %s에 대한 초기치를 위한 변환 오류가 발생했습니다.
ora-02355     constant 필드 %s에 변환 오류가 발생했습니다.
ora-02356     데이타베이스에 더 이상 영역이 없음 - 로드를 계속할 수 없습니다.
ora-02357     팩형 십진수 변환 오류
ora-02358     존 십진수 변환 오류
ora-02359     데이타 화일의 필드가 지정된 길이를 초과합니다.
ora-02360     논리 레코드의 끝 이전에 열을 찾을 수 없습니다 (trailing nullcols사용)
ora-02361     최초 인클로징 문자를 찾을 수 없습니다.
ora-02362     논리 레코드의 끝 - 두번째 인클로징 문자가 없습니다.
ora-02363     terminated 와 enclosed 가 지정된 필드에 종료 문자가 없습니다.
ora-02364     %s 레코드가 디스카드됨 - 모든 when 구의 조건을 만족하지 않습니다.
ora-02365     %s 색인이 로드되지 못함
ora-02366     %s 테이블의 다음 색인이 처리되었습니다.
ora-02367     %s 색인이 로드되었습니다.
ora-02368     %s 레코드가 디스카드됨 - 모든 열이 널입니다.
ora-02369     경고 : 가변길이 필드가 잘렸습니다.
ora-02370     %s 레코드 - %s 테이블의 %s 열에 경고 발생
ora-02371     직접 패스를 위해서는 로더가 %s.%s.%s.%s.%s 버전 이상 이어야 합니다.
ora-02372     상대시작 위치 > 절대필드 마감 위치
ora-02373     테이블 %s에 대한 입력 문의 구문분석시 오류
ora-02374     읽기 버퍼 큐에 대한 더 이상의 슬롯이 없습니다.
ora-02376     부당한 혹은 중복된 자원
ora-02377     자원의 부당한 한계치
ora-02378     중복된 자원명 %s
ora-02379     프로화일 %s이 이미 존재합니다.
ora-02380     프로화일 %s이 존재하지 않습니다.
ora-02381     public_default 프로화일을 삭제할 수 없습니다.
ora-02382     프로화일 %s에 사용자가 할당되어 있어, cascade 없이 삭제할 수 없습니다.
ora-02383     부당한 비용요소
ora-02390     composite_limit을 초과했음, 로그오프될 것입니다.
ora-02391     동시 sessions_per_user 한계치를 초과했습니다.
ora-02392     cpu 사용에 대한 세션 한계치를 초과했음. 로그오프될 것입니다.
ora-02393     cpu 사용에 대한 호출 한계치를 초과했습니다.
ora-02394     io 사용에 대한 세션 한계치를 초과했음. 로그오프될 것입니다.
ora-02395     io 사용에 대한 호출 한계치를 초과했습니다.
ora-02396     최대 유휴(idle) 시간을 초과했음. 다시 연결하십시오
ora-02397     private_sga 한계치 초과, 로그오프될 것입니다.
ora-02398     프로시저 영역 사용을 초과했습니다.
ora-02399     최대 연결시간을 초과했음. 로그오프될 것입니다.
ora-02401     다른 사용자의 뷰를 explain 할 수 없습니다.
ora-02402     plan_table이 없습니다.
ora-02403     플랜 테이블이 정확한 유형이 아닙니다.
ora-02404     지정된 플랜 테이블이 없습니다.
ora-02420     스키마에 대한 권한부여 절의 누락
ora-02421     누락 혹은 부당한 스키마 권한 식별자
ora-02422     누락 혹은 부당한 스키마 요소
ora-02423     스키마명이 스키마 권한 식별자와 맞지 않습니다.
ora-02424     잠재적인 순환 뷰 참조 혹은 불명의 참조 테이블
ora-02425     테이블의 생성실패
ora-02426     권한 부여 실패
ora-02427     뷰의 생성실패
ora-02428     외래키 참조를 추가할 수 없습니다.
ora-02429     유일/일차 키 적용을 위한 색인을 삭제할 수 없습니다.
ora-02430     제약(%s)을 가용화할 수 없음 - 그런 제약이 없습니다.
ora-02431     제약(%s)을 사용불가하게 할 수 없음 - 그런 제약이 없습니다.
ora-02432     일차키를 사용가능하게 할 수 없음 - 테이블에 일차키가 정의되지 않았습니다.
ora-02433     일차키를 사용불가하게 수 없음 - 테이블에 일차키가 정의되지 않았습니다.
ora-02434     유일성(%s)을 사용가능하게 할 수 없음 - 테이블에 일차키가 정의되지 않았습니다.
ora-02435     유일성(%s)을 사용불가하게 수 없음 - 테이블에 일차키가 정의되지 않았습니다.
ora-02436     check 제약에 날짜 또는 시스템 변수가 잘못 지정되었습니다.
ora-02437     (%s.%s)를 사용가능하게 할 수 없습니다 - 잘못된 기본 키입니다.
ora-02438     열 검사제약은 다른 열을 참조할 수 없습니다.
ora-02439     유일/일차 키 제약상에 유일하지 않은 색인이 있습니다.
ora-02440     참조 제약과 함께 create as select는 허용되지 않습니다.
ora-02441     존재하지 않는 일차 키를 삭제할 수 없습니다.
ora-02442     존재하지 않는 유일 키를 삭제할 수 없습니다.
ora-02443     존재하지 않는 제약 - 삭제할 수 없습니다.
ora-02444     참조 제약에서만 기본 테이블을 참조할 수 없습니다.
ora-02445     예외 테이블이 없습니다.
ora-02446     create table ... as select 실패 - 제약 위반 점검
ora-02450     부당한 해쉬 옵션 - 키워드 is 누락
ora-02451     hashkeys의 중복지정
ora-02452     부당한 hashkeys 옵션값
ora-02453     hash is의 중복 지정
ora-02454     블록(%s)당 해쉬 키의 수가 최대치 %s를 초과했습니다.
ora-02455     클러스터키 열의 수는 1 이어야 합니다.
ora-02456     열 지정 hash is는 number(*,0)이어야 합니다.
ora-02457     hash is 옵션에 정당한 열을 지정하여야 합니다.
ora-02458     hash cluster에 대하여 hashkeys가 지정되어야 합니다.
ora-02459     해쉬 키 값은 양의 정수이어야 합니다.
ora-02460     해쉬 클러스터에 대한 부적절한 색인 작업입니다.
ora-02461     index 옵션의 부적절한 사용입니다.
ora-02462     index 옵션의 중복지정
ora-02463     hash is 옵션의 중복지정
ora-02464     클러스터 정의는 hash와 index 양쪽 다 일수는 없습니다.
ora-02465     hash is 옵션의 부적절한 사용
ora-02466     hash clusters를 위해 size 옵션의 변경은 허용되지 않습니다.
ora-02467     식에 참조된 열을 클러스터 정의에서 찾을 수 없습니다.
ora-02468     식에서 상수 또는 시스템 변수가 잘못 지정되었습니다.
ora-02469     해쉬 식은 oracle 번호를 리턴하지 않습니다.
ora-02470     to_date, userenv, 또는 sysdate가 해쉬 식에서 잘못 사용되었습니다.
ora-02471     sysdate, uid, user, rownum, 또는 level이 해쉬 식에서 잘못 사용되었습니다.
ora-02472     해쉬 식에 pl/sql 함수를 사용할 수 없습니다.
ora-02473     클러스터 해쉬 식의 값을 구하는 동안 오류 발생
ora-02474     고정된 해쉬 영역이 (%s) 범위를 사용했는데 허용된 (%s) 최대값을 초과했습니다.
ora-02476     테이블에서 병렬 직접 로드에 의해 색인을 만들수 없습니다.
ora-02477     개체 %s에 병렬 직접 로드를 실행할 수 없습니다.
ora-02478     기초 세그먼트에 합병하는것은 maxextents 한계을 초과하는 것입니다.
ora-02479     병렬 로드에다 화일명을 바꾸는 중에 오류가 발생했습니다.
ora-02480     이벤트에 대한 너무 많은 이벤트 클래스가 지정되었습니다.
ora-02481     이벤트에 대한 너무 많은 id 범위가 지정되었습니다.
ora-02482     이벤트 클래스를 지정했으나 이벤트를 주지 않았습니다.
ora-02483     이벤트에 대한 부당한 id 값을 지정했습니다.
ora-02485     id 값의 하한치가 상한치보다 큽니다.
ora-02486     화일 %s에서 오류. init.ora 파라미터인 trace_dest를 확인하십시오
ora-02487     화일명 %s을 기록시 오류. init.ora 파라미터인 trace_dest를 검사하십시오
ora-02489     trace_block_size (%s)가 %s로 나누어져야 합니다.
ora-02490     resize 절에 필요한 화일 크기가 빠졌습니다.
ora-02491     autoextend 절에 필요한 on 또는 off 키워드가 빠졌습니다.
ora-02492     next 절에 필요한 화일 블록 증가 크기가 빠졌습니다.
ora-02493     next 절의 화일 증가 크기가 부적당합니다.
ora-02494     maxsize 절의 최대 화일 크기가 부적당하거나 빠졌습니다.
ora-02495     화일 %s의 크기를 조정할 수 없는데, 테이블스페이스 %s가 읽기전용이기 때문입니다.
ora-02700     osnoraenv: oracle_sid의 변환시 오류입니다.
ora-02701     osnoraenv: 오라클 이미지명의 변환시 오류입니다.
ora-02702     osnoraenv: orapop 이미지명의 변환시 오류입니다.
ora-02703     osnpopipe: 파이프 생성에 실패했습니다.
ora-02704     osndopop: 포크에 실패했습니다.
ora-02705     osnpol: 통신 채널의 폴링에 실패했습니다.
ora-02706     osnshs: 호스트명이 너무 깁니다.
ora-02707     osnacx: 문맥 영역을 할당할 수 없습니다.
ora-02708     osnrntab: 호스트로의 연결에 실패, oracle_sid가 불명입니다.
ora-02709     osnpop: 파이프 생성에 실패했습니다.
ora-02710     osnpop: 포크(fork)에 실패했습니다.
ora-02711     osnpvalid: 검증 채널로의 연결에 실패했습니다.
ora-02712     osnpop: malloc 실패
ora-02713     osnprd: 메세지 수신에 실패했습니다.
ora-02714     osnpwr: 메세지 송신에 실패했습니다.
ora-02715     osnpgetbrkmsg: 호스트로부터의 메시지가 부정확한 메시지 유형을 갖습니다.
ora-02716     osnpgetdatmsg: 호스트로부터의 메시지가 부정확한 메시지 유형을 갖습니다.
ora-02717     osnpfs: 기록된 바이트 수가 잘못되었습니다.
ora-02718     osnprs: 프로토콜 재설정 오류
ora-02719     osnfop: 포크(fork)에 실패했습니다.
ora-02720     osnfop: shmat 실패
ora-02721     osnseminit: 세마포 세트를 생성할 수 없습니다.
ora-02722     osnpui: orapop에 중지메시지를 송신할 수 없습니다.
ora-02723     osnpui: 중지메시지를 송신할 수 없습니다.
ora-02724     osnpbr: orapop에 중지메시지를 송신할 수 없습니다.
ora-02725     osnpbr: 중지메시지를 송신할 수 없습니다.
ora-02726     osnpop: 오라클 수행모듈의 액세스 오류입니다.
ora-02727     osnpop: orapop 수행모듈의 액세스 오류입니다.
ora-02728     osnfop: 오라클 수행모듈의 액세스 오류입니다.
ora-02729     osncon: 드라이버가 osntab내에 없습니다.
ora-02730     osnrnf: 사용자 로그온 디렉토리가 없습니다.
ora-02731     osnrnf: 버퍼의 malloc에 실패했습니다.
ora-02732     osnrnf: 일치하는 데이타베이스 별명을 발견할 수 없습니다.
ora-02733     osnsnf: 데이테베이스 스트링이 너무 깁니다.
ora-02734     osnftt: 공유 메모리의 사용허가를 재설정할 수 없습니다.
ora-02735     osnfpm: 공유 메모리 세그먼트를 생성할 수 없습니다.
ora-02736     osnfpm: 부적절한 공유메모리 번지의 디폴트치입니다.
ora-02737     osnpcl: orapop의 종료를 명령할 수 없습니다.
ora-02738     osnpwrtbrkmsg: 기록된 바이트 수가 잘못되었습니다.
ora-02739     osncon: 호스트 별명이 너무 깁니다.
ora-02750     osnfsmmap: 공유메모리 화일(?/dbs/ftt_<pid>.dbf)을 열 수 없습니다.
ora-02751     osnfsmmap: 공유메모리 화일을 배치할 수 없습니다.
ora-02752     osnfsmmap: 부당한 공유메모리 번지입니다.
ora-02753     osnfsmmap: 공유메모리 화일을 닫을 수 없습니다.
ora-02754     osnfsmmap: 공유메모리의 형질을 변경할 수 없습니다.
ora-02755     osnfsmcre: 공유메모리 화일(?/dbs/ftt_<pid>.dbf)을 생성할 수 없습니다.
ora-02756     osnfsmnam: 이름 변환에 실패했습니다.
ora-02757     osnfop: fork_and_bind 실패
ora-02758     내부배열의 할당에 실패했습니다.
ora-02759     요구 디스크립터가 충분하지 않습니다.
ora-02760     클라이언트의 화일 닫기 실패
ora-02761     취소될 화일 번호가 음수입니다.
ora-02762     취소될 화일 번호가 최대치보다 큽니다.
ora-02763     최소 한건의 요구도 취소할 수 없습니다.
ora-02764     부당한 패키지 모드입니다.
ora-02765     부당한 최대 서버수입니다.
ora-02766     요구 디스크립터의 부당한 최대치입니다.
ora-02767     서버당 하나 이하의 요구 디스크립터가 할당되었습니다.
ora-02768     최대 화일수가 부적절합니다.
ora-02769     sigterm에 대한 처리기 지정이 실패했습니다.
ora-02770     전체 블록수가 부적절합니다.
ora-02771     요구 타임아웃 값이 부적절합니다.
ora-02772     서버의 최대 유휴 시간이 부적절합니다.
ora-02773     클라이언트의 최대 대기시간이 부적절합니다.
ora-02774     요구 목록 래치의 타임아웃값이 부적절합니다.
ora-02775     요구 수행 신호가 부적절합니다.
ora-02776     요구 수행 신호값이 최대치를 초과합니다.
ora-02777     로그 디렉토리에 대한 stat실패
ora-02778     로그 디렉토리에 주어진 이름이 부적합합니다.
ora-02779     코아덤프 디렉토리에 대한 stat실패
ora-02780     코아덤프 디렉토리에 주어진 이름이 부적합합니다.
ora-02781     시간이 주어지는 플래그에 대한 값이 부적합합니다.
ora-02782     읽기/쓰기 기능이 모두 지정되지 않았습니다.
ora-02783     포스트/대기 기능이 모두 지정되지 않았습니다.
ora-02784     부적절한 공유 메모리 id가 지정되었습니다.
ora-02785     부적절한 공유 메모리 버퍼크기입니다.
ora-02786     공유 영역에 필요한 크기가 세그먼트 크기보다 큽니다.
ora-02787     세그먼트 목록에 대한 메모리를 할당할 수 없습니다.
ora-02788     async 프로세스 배열내에 커널 프로세스 포인터를 찾을 수 없습니다.
ora-02789     최대 화일 수에 도달했습니다.
ora-02790     화일명이 너무 깁니다.
ora-02791     비동기 i/o에 사용될 화일을 열 수 없습니다.
ora-02792     비동기 i/o에 사용될 화일을 fstat()할 수 없습니다.
ora-02793     비동기 i/o의 닫기 실패
ora-02794     클라이언트가 공유메모리에 대한 키를 얻을 수 없습니다.
ora-02795     요구 목록이 비었습니다.
ora-02796     수행된 요구가 정확한 상태에 있지 않습니다.
ora-02797     모든 요구에 응답할 수 없습니다.
ora-02798     요구 수가 부적절합니다.
ora-02799     신호 처리기를 대비할 수 없습니다.
ora-02800     요구가 시간 경과되었습니다.
ora-02801     작업이 시간 경과되었습니다.
ora-02802     모든 유휴 서버를 병렬모드에서 사용할 수 없습니다.
ora-02803     현재 시간의 추출에 실패했습니다.
ora-02804     로그 화일명에 대한 메모리 할당에 실패했습니다.
ora-02805     sigtpa에 대한 처리기를 지정할 수 없습니다.
ora-02806     sigalrm에 대한 처리기를 지정할 수 없습니다.
ora-02807     i/o 벡터에 대한 메모리 할당에 실패했습니다.
ora-02808     서버가 사용하는 flag array를 위한 메모리 할당에 실패했습니다.
ora-02809     jump 버퍼가 적절하지 않습니다.
ora-02810     메모리 맵화일에 대한 임시 화일명을 만들수 없습니다.
ora-02811     공유메모리 세그먼트를 첨부할 수 없습니다.
ora-02812     잘못된 첨부 번지입니다.
ora-02813     키를 얻기위한 임시화일명을 만들수 없습니다.
ora-02814     공유 메모리를 얻을 수 없습니다.
ora-02815     공유 메모리를 첨부할 수 없습니다.
ora-02816     프로세스를 죽일 수 없습니다.
ora-02817     읽기실패
ora-02818     요구된 것보다 적은 수의 블록이 읽혀졌습니다.
ora-02819     쓰기실패
ora-02820     요구된 수의 블록을 기록할 수 없습니다.
ora-02821     요구된 수의 블록을 읽을 수 없습니다.
ora-02822     부적절한 블록 오프셋
ora-02823     버퍼가 정열되지 않았습니다.
ora-02824     가용 요구 목록이 비었습니다.
ora-02825     자유롭게 선택할 수 있는 목록에 대한 요구가 해제되지 않았습니다.
ora-02826     부적절한 블록크기 입니다.
ora-02827     부당한 화일번호입니다.
ora-02828     가용 세그먼트 목록이 비었습니다.
ora-02829     적절한 크기의 세그먼트가 없습니다.
ora-02830     세그먼트는 파티션될 수 없음 - 가용 세그먼트가 없습니다.
ora-02831     세그먼트 할당해제 실패 - 세그먼트 목록이 비었습니다.
ora-02832     세그먼트 할당해제 실패 - 세그먼트가 목록에 없습니다.
ora-02833     서버가 화일을 닫을 수 없습니다.
ora-02834     서버가 화일을 열 수 없습니다.
ora-02835     서버가 클라이언트에 신호을 송신할 수 없습니다.
ora-02836     임시 키 화일을 생성할 수 없습니다.
ora-02837     임시 화일을 링크 해제할 수 없습니다.
ora-02838     알람 신호를 위한 신호처리기를 대비할 수 없습니다.
ora-02839     디스크로 블록을 sync하는데 실패했습니다.
ora-02840     클라이언트가 로그 화일을 여는데 실패했습니다.
ora-02841     기동시 서버가 죽었습니다.
ora-02842     클라이언트가 서버를 포크할 수 없습니다.
ora-02843     커널 플래그에 대한 부적절한 값입니다.
ora-02844     열기 허가 플래그에 대한 부적절한 값입니다.
ora-02845     시각 요구 플래그에 대한 부적절한 값입니다.
ora-02846     중지시킬 수 없는 서버입니다.
ora-02847     포스트시 서버가 종료되지 않았습니다.
ora-02848     비동기 i/o 패키지가 가동중이 아닙니다.
ora-02849     오류로 인한 읽기 실패
ora-02850     화일이 닫혔습니다.
ora-02851     비어있지 않아야할 요구 목록이 비었습니다.
ora-02852     위험 부분에 대한 부적절한 타임아웃 값입니다.
ora-02853     서버 목록 래치 타임아웃 값이 부적절합니다.
ora-02854     요구 버퍼의 수가 부적절합니다.
ora-02855     요구건수가 slaves수 보다 작습니다.
ora-03001     현재에는 구현되어 있지 않은 기능입니다.
ora-03002     이 연산자는 구현되어 있지 않습니다.
ora-03007     이 기능은 폐지되었습니다.
ora-03008     파라미터 compatible >= %s 가 %s에 필요합니다.
ora-03100     통신 영역이 할당되지 않음. 메모리가 충분하지 않습니다.
ora-03105     내부 프로토콜 오류
ora-03106     두 태스크 간의 통신 프로토콜 오류입니다.
ora-03107     oranet 버퍼 언더플로우입니다.
ora-03108     oranet: oracle은 이 인터페이스 버전을 지원하지 않습니다.
ora-03109     oranet 버퍼 오버플로우입니다.
ora-03110     oranet: oracle은 이 sql 버전을 지원하지 않습니다.
ora-03111     통신 채널에서 브레이크를 수신했습니다.
ora-03112     단일-태스크로 링크된 서버는 sql*net을 사용할 수 없습니다.
ora-03113     통신 채널에 eof 가 있습니다.
ora-03114     oracle에 연결되어 있지 않습니다.
ora-03115     지원되지 않은 네트워크 데이타 유형 또는 표현이 있습니다.
ora-03116     부적당한 버퍼 길이가 변환 루틴으로 전달되었습니다.
ora-03117     2-타스크 보존 영역 오버플로우
ora-03118     2-타스크 코루틴의 상태가 부적당합니다.
ora-03120     2-타스크 변환 루틴: 정수 오버플로우
ora-03121     인터페이스 드라이버가 연결되어 있지 않습니다 함수는 실행되지 않습니다.
ora-03122     사용자측에서 oracle측의 윈도우를 클로즈하려 했습니다.
ora-03123     작업이 막힘
ora-03124     2-타스크 내부 오류
ora-03125     클라이언트-서버 프로토콜에 위배됩니다.
ora-03126     네트워크 드라이버가 비-블로킹 작업을 지원하지 않습니다.
ora-03127     실행 작업이 종료되기 전에는 새로운 작업을 할 수 없습니다.
ora-03128     연결은 블로킹 모드입니다.
ora-03129     다음 구분이 삽입되도록 요청했습니다.
ora-03130     다음 구분이 인출 되도록 요청한 버퍼입니다.
ora-03131     다음 구분을 위한 버퍼가 잘못 제공되었습니다.
ora-03200     세그먼트 유형 명세가 부적당합니다.
ora-03201     그룹 번호 명세가 부적당합니다.
ora-03202     스캔 한계 명세가 부적당합니다.
ora-03203     동시 갱신은 영역 분석을 불가능하게 합니다.
ora-03230     세그먼트는 %s 블록만을 포함하고 있습니다.
ora-03231     initial 영역이 할당 해제되지 않았습니다.
ora-03274     allocate extent와 deallocate unused 옵션들이 지정되었습니다.
ora-03275     이중 deallocate 옵션으로 명세
ora-03276     allocate extent의 중복지정
ora-03277     부적절한 size의 지정
ora-03278     allocate extent 옵션의 중복지정
ora-03279     부적절한 instance가 지정되었음
ora-03280     부적절한 datafile 화일명의 지정
ora-03281     부적절한 allocate extent 옵션
ora-03282     allocate extent 옵션의 누락
ora-03283     지정된 데이타 화일 %s이 존재하지 않습니다.
ora-03284     데이타 화일 %s는 테이블스페이스 %s의 멤버가 아닙니다.
ora-03286     hash clusters에 대해 allocate extent가 정당하지 않습니다.
ora-03287     부적절한 freelist group의 지정
ora-03288     freelist group과 instance 파라미터가 함께 지정될 수 없습니다.
ora-03290     부적절한 truncate 명령어 - cluster 혹은 table 키워드의 누락
ora-03291     부적절한 truncate 옵션 - storage 키워드의 누락
ora-03292     잘릴 테이블이 클러스터의 일부입니다.
ora-03293     잘릴 클러스터는 hash cluster입니다.
ora-03296     데이타화일의 크기를 조정할 수 없습니다 - 화일 %s 이 없습니다.
ora-03297     요구된 resize 값보다 큰 %s 데이타 블록이 화일에 포함되어 있습니다.
ora-03298     데이타화일을 줄일 수 없습니다 - 화일 %s는 핫 백업중입니다.
ora-03299     딕셔너리 테이블 %s을 생성할 수 없습니다.
ora-04000     pctused 와 pctfree 의 합이 100을 초과할 수 없습니다.
ora-04001     시퀀스 파라미터 %s 는 정수라야 합니다.
ora-04002     increment 는 0이 아닌 정수라야 합니다.
ora-04003     시퀀스 파라미터 %s가 최대 크기 허용(%s 자리)를 초과했습니다.
ora-04004     minvalue 는 maxvalue 보다 작아야 합니다.
ora-04005     increment 는 ( maxvalue - minvalue ) 보다 작아야 합니다.
ora-04006     start with 에 minvalue 보다 작은 값은 지정할 수 없습니다.
ora-04007     minvalue 에 현재치보다 큰 값을 지정할 수 없습니다.
ora-04008     start with 에 maxvalue 보다 큰 값을 지정할 수 없습니다.
ora-04009     maxvalue 에 현재치보다 작은 값을 지정할 수 없습니다.
ora-04010     cache 에는 1 보다 큰 수치를 지정해야 합니다.
ora-04011     시퀀스 %s 은 %s 와 %s 범위 사이어야 합니다.
ora-04012     지정된 개체는 시퀀스가 아닙니다.
ora-04013     cache 에는 1 사이클보다 작은 값을 지정해야 합니다.
ora-04014     cycle이 명시하는 minvalue가 내림차순 시퀀스입니다.
ora-04015     cycle 을 실시하는 오름차순 시퀀스에는 maxvalue 를 지정해야 합니다.
ora-04016     시퀀스 %s 은 더 이상 존재하지 않습니다.
ora-04020     개체 %s%s%s%s%s의 잠금 시도중 데드록이 검출되었습니다.
ora-04021     개체 %s%s%s%s%s의 잠금 대기중 시간이 초과됐습니다.
ora-04028     개체 %s%s%s%s%s에 대한 diana를 생성할 수 없습니다.
ora-04029     %s%s%s를 조회하는 중에 ora-%s 오류가 발생했습니다.
ora-04030     %s바이트 (%s,%s)의 할당 시도중 프로세스 메모리의 부족현상 발생
ora-04031     %s 바이트의 공유 메모리를 할당할 수 없습니다 (%s,%s,%s)
ora-04041     패키지 본체의 생성전에 패키지 지정이 먼저 생성되어야 합니다.
ora-04042     프로시저,함수,패키지 혹은 패키지 본체가 존재하지 않습니다.
ora-04043     개체 %s가 존재하지 않습니다.
ora-04044     프로시저, 함수, 패키지는 이곳에서 허용되지 않습니다.
ora-04045     %s.%s의 재 컴파일/재 검증시 오류
ora-04046     컴파일 결과를 제공하기에는 너무 큽니다.
ora-04050     부적절한 혹은 누락된 프로시저, 함수, 혹은 패키지명입니다.
ora-04051     사용자 %s는 데이타베이스 링크 %s.%s를 사용할 수 없습니다.
ora-04052     원격 개체 %s%s%s%s%s를 찾는 동안 오류발생
ora-04053     원격 개체 %s%s%s%s%s의 검증시 오류발생
ora-04054     데이타베이스 링크 %s가 존재하지 않습니다.
ora-04060     %s를 수행하기 위한 권한이 부족합니다.
ora-04061     %s의 기존상태가 무효화되었습니다.
ora-04062     %s(%s의)이 변경되었습니다.
ora-04063     %s가 오류를 가집니다.
ora-04064     실행불가, %s가 무효화 되었습니다.
ora-04065     실행불가, %s가 변경 혹은 삭제되었습니다.
ora-04066     실행할수 없는 개체, %s
ora-04067     실행불가, %s가 존재하지 않습니다.
ora-04068     패키지%s%s%s의 기존 상태가 버려졌습니다.
ora-04070     부적절한 트리거명
ora-04071     before 혹은 after 키워드의 누락
ora-04072     부적절한 트리거유형
ora-04073     이 트리거유형에 대해서 열 목록은 부당합니다.
ora-04074     부적절한 referencing명
ora-04075     부적절한 트리거동작
ora-04076     부적절한 new 혹은 old지정
ora-04077     when절은 레이블 레벨의 트리거와 사용될 수 없습니다.
ora-04078     old와 new값이 같을 수 없습니다.
ora-04079     부당한 트리거 지정
ora-04080     트리거 %s가 존재하지 않습니다.
ora-04081     트리거 %s가 이미 존재합나다.
ora-04082     테이블 레벨 트리거에서 new 혹은 old 참조는 허용되지 않습니다.
ora-04083     부적절한 트리거 변수 %s
ora-04084     행 트리거후에 트리거의 new값을 변경할 수 없습니다.
ora-04085     old 참조변수의 값을 변경할 수 없습니다.
ora-04086     트리거 설명이 너무 깁니다 트리거 코드에 주석을 옮기십시오
ora-04087     rowid 참조 변수의 값을 변경할 수 없습니다.
ora-04088     트리거 %s의 수행시 오류
ora-04089     sys 소유의 개체에 대한 트리거를 작성할 수 없습니다.
ora-04090     %s는 동일 테이블, 이벤트 그리고 트리거 시간을 %s 로 지정하고 있습니다.
ora-04091     테이블 %s.%s가 변화하고 있어서 트리거/함수가 이를 볼 수 없습니다.
ora-04092     트리거 안에 %s를 할 수 없습니다.
ora-04093     long유형 열 참조는 트리거에서 허용되지 않습니다.
ora-04094     테이블 %s.%s은 부적합함, 트리거는 그것을 수정할 수 없습니다.
ora-04095     트리거 %s가 다른 테이블에 이미 존재함, 치환할 수 없습니다.
ora-04096     트리거 %s는 when 절이 있은데 너무 큽니다 한계치가 2k.
ora-04097     트리거 삭제 또는 수정을 시도시 ddl 대립이 생겼습니다.
ora-04098     트리거 %s 은 부적당하고 재검증에 실패했습니다.
ora-04099     트리거 %s 은 적당하지만 컴파일된 폼에 저장되지 않았습니다.
ora-06000     netasy: 포트 개방 실패
ora-06001     netasy: 포트 셋업 실패
ora-06002     netasy: 포트 읽기 실패
ora-06003     netasy: 포트 쓰기 실패
ora-06004     netasy: 대화 화일의 개방 실패
ora-06005     netasy: 대화 화일의 읽기 실패
ora-06006     netasy: 대화의 수행 실패
ora-06007     netasy: 잘못된 대화 유형
ora-06009     netasy: 대화 화일명이 너무 깁니다.
ora-06010     netasy: 대화 화일이 너무 깁니다.
ora-06011     netasy: 대화가 너무 깁니다.
ora-06017     netasy: 메시지 수신 실패
ora-06018     netasy: 메시지 송신 실패
ora-06019     netasy: 부적절한 로그인(연결) 스트링
ora-06020     netasy: 초기화 실패
ora-06021     netasy: 연결 실패
ora-06022     netasy: 채널 개방 실패
ora-06023     netasy: 포트 개방 실패
ora-06024     netasy: vtm 오류
ora-06025     netasy: 환경설정 오류
ora-06026     netasy: 포트 close 실패
ora-06027     netasy: 채널 close 실패
ora-06028     netasy: 로그인 하기위한 초기화를 할 수 없습니다.
ora-06029     netasy: 포트 할당 실패
ora-06030     netdnt: 연결 실패, 인식할 수 없는 노드명입니다.
ora-06031     netdnt: 연결 실패, 인식할 수 없는 개체명입니다.
ora-06032     netdnt: 연결 실패, 제어정보의 액세스가 거절되었습니다.
ora-06033     netdnt: 연결 실패, 상대편이 연결을 거절했습니다.
ora-06034     netdnt: 연결 실패, 상대편이 예기치않게 종료됐습니다.
ora-06035     netdnt: 연결 실패, 불충분한 자원입니다.
ora-06036     netdnt: 연결 실패, 개체로부터의 응답이 없습니다.
ora-06037     netdnt: 연결 실패, 노드에 도달할 수 없습니다.
ora-06038     netdnt: 연결 실패, 네트워크 드라이버가 로드되지 않았습니다.
ora-06039     netdnt: 연결 실패
ora-06040     netdnt: 부적절한 로그인 스트링입니다.
ora-06041     netdnt: 분리 실패
ora-06042     netdnt: 메시지 수신 실패
ora-06043     netdnt: 메시지 송신 실패
ora-06044     netdnt: 연결 실패, 바이트 갯수 할당량을 초과했습니다.
ora-06102     nettcp: 문맥 영역을 할당할 수 없습니다.
ora-06105     nettcp: 원격 호스트가 불명입니다.
ora-06106     nettcp: 소켓 생성 실패
ora-06107     nettcp: oracle 네트워크 서버가 없습니다.
ora-06108     nettcp: 호스트에 연결 실패
ora-06109     nettcp: 메시지 수신 실패
ora-06110     nettcp: 메시지 송신 실패
ora-06111     nettcp: 분리하는것이 실패
ora-06112     nettcp: 부적절한 버퍼크기입니다.
ora-06113     nettcp: 연결이 너무 많습니다.
ora-06114     nettcp: sid 찾기 실패
ora-06115     nettcp: 논리적인 oracle을 생성할 수 없습니다.
ora-06116     nettcp: orasrv 프로세스를 생성할 수 없습니다.
ora-06117     nettcp: orasrv를 생성할 수 없음: 할당량을 초과했습니다.
ora-06118     nettcp: orasrv와의 교신을 끝낼 수 없습니다.
ora-06119     nettcp: 가짜 클라이언트의 요구
ora-06120     nettcp: 네트워크 드라이버가 로드되지 않았습니다.
ora-06121     nettcp: 액세스 실패
ora-06122     nettcp: 셋업 실패
ora-06123     nettcp: keepalive를 지정할 수 없습니다.
ora-06124     nettcp: orasrv 대기시 시간경과
ora-06125     nettcp: orasrv가 예기치않게 종료했습니다.
ora-06126     nettcp: orasrv가 네트워크 연결을 열 수 없습니다.
ora-06127     nettcp: 사용자명을 변경할 수 없습니다.
ora-06128     nettcp: 우편함을 생성할 수 없습니다.
ora-06129     nettcp: 소켓의 소유권을 orasrv로 옮길 수 없습니다.
ora-06130     nettcp: 호스트의 액세스가 거부되었습니다.
ora-06131     nettcp: 사용자의 액세스가 거부되었습니다.
ora-06132     nettcp: 비밀번호가 틀림, 액세스가 거부되었습니다.
ora-06133     nettcp: 화일이 없습니다.
ora-06134     nettcp: 화일 액세스 권한이 위반되었습니다.
ora-06135     nettcp: 연결이 거절됨; 서버가 중지되고 있습니다.
ora-06136     nettcp: 연결교신중 오류 발생
ora-06137     nettcp: 연결교신중 오류 발생
ora-06138     nettcp: 연결교신중 오류 발생
ora-06140     nettcp: 그런 사용자가 없습니다.
ora-06141     nettcp: 사용자에 대한 권한이 없습니다.
ora-06142     nettcp: 사용자 정보의 획득시 오류
ora-06143     nettcp: 최대 연결수를 초과했습니다.
ora-06144     nettcp: sid (데이타베이스)는 사용할 수 없습니다.
ora-06145     nettcp: orasrv를 수행시킬 수 없음: 이미지가 설치되지 않았습니다.
ora-06200     twotask: 연결 실패, 우편함을 생성할 수 없습니다.
ora-06201     twotask: 연결 실패, 우편함에 연결할 수 없습니다.
ora-06202     twotask: 연결 실패, 서버 태스크를 만들 수 없습니다.
ora-06203     twotask: 연결 실패, 교신 실패
ora-06204     twotask: 연결 실패, orasrv2.com를 액세스할 수 없습니다.
ora-06205     twotask: 연결 실패, 논리명을 생성할 수 없습니다.
ora-06206     twotask: 메시지 수신 실패
ora-06207     twotask: 메시지 송신 실패
ora-06208     twotask: 부적당한 로그인(연결) 스트링
ora-06209     twotask: 연결 실패, 우편함이 이미 존재하고 있습니다.
ora-06210     twotask: 연결 실패, orasrv가 예기치 않게 종료되었습니다.
ora-06211     twotask: 연결 실패, orasrv를 기다리다가 시간 초과 되었습니다.
ora-06212     twotask: 연결 실패, 논리 이름 테이블이 꽉 차있습니다.
ora-06213     twotask: 연결 실패
ora-06214     twotask: 연결 실패, orasrv를 생성하기 위해 충분치 않은 할당량 입니다.
ora-06215     twotask: 연결 실패, orasrv 이미지가 설치가 않되게 보호된 것입니다.
ora-06216     twotask: 연결 실패, orasrv 이미지 화일을 발견할 수 없습니다.
ora-06250     netntt: 송수신 버퍼를 할당할 수 없습니다.
ora-06251     netntt: 주소 화일명을 해석할 수 없습니다.
ora-06252     netntt: 주소 화일을 열 수 없습니다.
ora-06253     netntt: 주소화일에서 인수를 read 할 수 없습니다.
ora-06254     netntt: 큐브로의 연결을 공유할 수 없습니다.
ora-06255     netntt: 원격 프로세스의 pid를 read 할수없습니다.
ora-06256     netntt: 원격 fork 실패
ora-06257     netntt: 섀도(shadow) 프로세스에 명령을 송신할 수 없습니다.
ora-06258     netntt: 문맥 영역을 할당할 수 없습니다.
ora-06259     netntt: 원격 프로세스에서 read 할수 없습니다.
ora-06260     netntt: 원격 프로세스로 write 할수 없습니다.
ora-06261     netntt: nrange() 실패
ora-06262     netntt: nfconn() 실패
ora-06263     netntt: pi_connect에 메모리 부족
ora-06264     netntt: 데이타 프로토콜 오류
ora-06265     netntt: break 프로토콜 오류
ora-06266     netntt: 잘못된 쓰기 길이
ora-06267     netntt: 오류 상태
ora-06268     netntt: /etc/oratab을 read 불가
ora-06300     ipa: 접속분리 실패
ora-06301     ipa: driver context 를 할당할 수 없습니다.
ora-06302     ipa: 원격 호스트에 연결 불가
ora-06303     ipa: 메세지 전송 오류
ora-06304     ipa: 메세지 수신 오류
ora-06305     ipa: 부적절한 메시지 유형
ora-06306     ipa: 메세지 write 길이 오류
ora-06307     ipa: 연결 재설정 실패
ora-06308     ipa: 더 이상 연결 불가
ora-06309     ipa: 이용 가능한 메세지 큐가 없음
ora-06310     ipa: 환경 변수가 지정되지 않았습니다.
ora-06311     ipa: 최대 서버수에 도달 했습니다.
ora-06312     ipa: 지정된 서비스명이 부정확합니다.
ora-06313     ipa: 공유 메모리 초기화 실패
ora-06314     ipa: event 설정 실패
ora-06315     ipa: 콘넥트 스트링 오류
ora-06316     ipa: 데이타베이스 sid 오류
ora-06317     ipa: 로컬 최대 사용자수 초과
ora-06318     ipa: 로컬 최대 콘넥션수 초과
ora-06319     ipa: 원격 최대 사용자수 초과
ora-06320     ipa: 원격 최대 연결 수 초과
ora-06321     ipa: 원격편에 도달할 수 없습니다.
ora-06322     ipa: 심각한 공유 메모리 오류
ora-06323     ipa: 이벤트 오류 발생
ora-06400     netcmn: 지정된 기본 호스트 뮨자열이 없습니다.
ora-06401     netcmn: 부적절한 드라이버 지정자
ora-06402     netcmn: 브레이크 메시지 수신시 오류
ora-06403     netcmn: 문맥 영역을 할당할 수 없습니다.
ora-06404     netcmn: 부당한 로그인 (연결) 스트링
ora-06405     netcmn: 프로토콜 재설정 오류
ora-06406     netcmn: 브레이크 메시지 송신시 오류
ora-06407     netcmn: 브레이크 처리환경을 구축할 수 없습니다.
ora-06408     netcmn: 부정확한 메시지 유형
ora-06413     연결이 개방되지 않았습니다.
ora-06416     netcmn: 테스트시 오류
ora-06419     netcmn: 서버가 오라클을 기동시킬 수 없습니다.
ora-06420     netcmn: sid의 찾기 실패
ora-06421     netcmn: 읽혀질 데이타에 오류가 발견되었습니다.
ora-06422     netcmn: 송신 데이타에 오류가 발견되었습니다.
ora-06423     netcmn: 수신 데이타에 오류가 발견되었습니다.
ora-06430     ssaio: 함수가 잘못된 인수로 요구되었습니다.
ora-06431     ssaio: 부적절한 블록번호
ora-06432     ssaio: 버퍼가 정열되지 않습니다.
ora-06433     ssaio: lseek 오류, 요구된 블록을 찾을 수 없습니다.
ora-06434     ssaio: 읽기 오류, 데이타베이스 화일로 읽을 수 없습니다.
ora-06435     ssaio: 쓰기 오류, 데이타베이스 화일에 기록할 수 없습니다.
ora-06436     ssaio: 비동기 i/o가 틀린 파라미터로 인하여 실패했습니다.
ora-06437     ssaio: 비동기 쓰기는 데이타베이스 화일에 기록할 수 없습니다.
ora-06438     ssaio: 비동기 읽기는 데이타베이스 화일로 부터 읽을 수 없습니다.
ora-06439     ssaio: 비동기 쓰기가 틀린 바이트 수를 리턴했습니다.
ora-06440     ssaio: 비동기 읽기가 틀린 바이트 수를 리턴했습니다.
ora-06441     ssvwatev: 함수 호출에 잘못된 파라미터가 넘겨졌습니다.
ora-06442     ssvwatev: 예기치 않은 오류로 실패했습니다.
ora-06443     ssvpstev: 함수 호출에 잘못된 파라미터가 넘겨졌습니다.
ora-06444     ssvpstev: 예기치 않은 오류로 실패했습니다.
ora-06445     ssvpstevrg: 함수 호출에 잘못된 파라미터가 넘겨졌습니다.
ora-06446     ssvpstevrg: 예기치 않은 오류로 실패했습니다.
ora-06447     ssvpstp: 함수 호출에 잘못된 파라미터가 넘겨졌습니다.
ora-06448     ssvpstp: 예기치 않은 오류로 실패했습니다.
ora-06449     리스트 io 혹은 sysvendor가 설치되지 않았습니다.
ora-06500     pl/sql: 기억 영역 오류입니다.
ora-06501     pl/sql 프로그램 오류
ora-06502     pl/sql: 값(수치) 오류입니다.
ora-06503     pl/sql: 함수가 값을 리턴하지 못했습니다.
ora-06504     pl/sql: result set 변수 또는 질의의 리턴 유형이 일치하지 않습니다.
ora-06508     pl/sql: 호출되는 lib 단위를 발견할 수 없습니다.
ora-06509     pl/sql: 이 패키지(package)에 대한 icd 벡터가 누락됐습니다.
ora-06510     pl/sql: 처리되지 않은 user-defined 예외 상황
ora-06511     pl/sql: 커서가 이미 열려있습니다.
ora-06512     %s줄 %s에서
ora-06513     pl/sql: pl/sql 테이블의 색인이 호스트 언어 배열의 범위를 벗어남
ora-06514     pl/sql: 원격 호출은 서버에 의해서 처리되지 않습니다.
ora-06540     pl/sql: 컴파일 오류
ora-06541     pl/sql: 컴파일 오류 - 컴파일 중지
ora-06542     pl/sql: 실행 오류
ora-06543     pl/sql: 실행 오류 - 실행 중지
ora-06544     pl/sql: 내부 오류, 인수: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]
ora-06550     줄 %s, 열%s:%s
ora-06551     pl/sql: 처리되지 않은 예외상황
ora-06552     pl/sql: %s
ora-06553     pls-%s: %s
ora-06554     패키지 dbms_standard는 pl/sql을 사용하기 전에 생성되야만 합니다.
ora-06555     이 이름은 현재 사용자 sys에 의해 사용되기 위해 예약되어 있습니다.
ora-06556     파이프가 비어 있어 unpack_message 요구를 이행할 수 없습니다.
ora-06557     icd 파이프에 대한 파라미터로 null 값은 허용되지 않습니다.
ora-06558     dbms_pipe 패키지에 있는 버퍼가 꽉 찼음. 더 이상의 항목이 사용될 수 없습니다.
ora-06559     %s로 잘못된 데이타유형이 요구되었습니다, 실제 데이타유형은 %s 입니다.
ora-06560     위치, %s 가 버퍼 크기 %s 보다 크거나 음수 입니다.
ora-06561     명령문이 dbms_sql 패키지에 의해 지원되지 않습니다.
ora-06562     out 인수의 형이 열의 형과 일치되거나 변수와 바인드되어야 합니다.
ora-06563     기술된 최상위 레벨의 프로시저/펑션이 하위레벨을 포함할 수 없습니다.
ora-06564     개체 %s가 존재하지 않습니다.
ora-06565     저장된 프로시저에서 %s를 실행할 수 없습니다.
ora-06566     행의 수 지정이 부적합합니다.
ora-06567     값의 수 지정이 부적합합니다.
ora-06568     폐기된 icd 프로시저가 호출되었습니다.
ora-06570     풀 개체 공유가 존재하지 않습니다.
ora-06571     %s 함수는 데이타베이스에 갱신하는것을 보증할 수 없습니다.
ora-06572     %s 함수는 out 인수를 가지고 있습니다.
ora-06573     %s 함수가 패키지 상태를 변경하는데, 여기서는 사용할 수 없습니다.
ora-06574     %s 함수는 패키지 상태를 참조하는데, 원격적으로 실행할 수 없습니다.
ora-06575     패키지 또는 함수 %s 은 부적당한 상태입니다.
ora-06580     해쉬 결합이 큰 행을 메모리에 보관하는 중에 메모리 부족이 일어났습니다.
ora-06600     lu6.2 driver: sna 소프트웨어가 로드되지 않음
ora-06601     lu6.2 driver: 부적절한 데이타베이스 id 스트링임
ora-06602     lu6.2 driver: 문맥 영역 할당시 오류
ora-06603     lu6.2 driver: 메모리 할당시 오류
ora-06604     lu6.2 driver: 원격 lu와 함께 세션을 할당할 수 없음
ora-06605     lu6.2 driver: 예기치 않은 줄 턴어라운드
ora-06606     lu6.2 driver: sna로 부터의 예기치 않은 응답
ora-06607     lu6.2 driver: 송신상태에서 재설정됨
ora-06608     lu6.2 driver: 수신상태에서 재설정됨
ora-06610     lu6.2 driver: 해제시 실패
ora-06611     lu6.2 driver: 송신 요구오류
ora-06612     lu6.2 driver: 데이타 송신오류
ora-06613     lu6.2 driver: 수신 및 대기오류
ora-06614     lu6.2 driver: 즉시 수신오류
ora-06615     lu6.2 driver: 송신오류
ora-06616     lu6.2 driver: lu로의 첨부에 실패했음
ora-06617     lu6.2 driver: pu로의 첨부에 실패했음
ora-06618     lu6.2 driver: 서브네트워크의 활성화에 실패했음
ora-06619     lu6.2 driver: 활성적인 원격 파트너를 할 수 없습니다.
ora-06620     lu6.2 driver: 부적절한 원격 파트너
ora-06621     lu6.2 driver: 할당 오류
ora-06622     lu6.2 driver: sna에 첨부할 수 없음
ora-06700     tli driver: 호스트로부터의 메시지 유형이 부정확합니다.
ora-06701     tli driver: 틀린 수의 바이트가 기록되었습니다.
ora-06702     tli driver: 문맥 영역을 할당할 수 없습니다.
ora-06703     tli driver: 브레이크 메시지의 송신 실패
ora-06704     tli driver: 브레이크 메시지의 수신 실패
ora-06705     tli driver: 원격 노드가 불명입니다.
ora-06706     tli driver: 서비스가 발견되지 않습니다.
ora-06707     tli driver: 연결실패
ora-06708     tli driver: 메시지 수신실패
ora-06709     tli driver: 메시지 송신실패
ora-06710     tli driver: 송신 인터럽트 브레이크 메시지 실패
ora-06711     tli driver: 바인드시 오류
ora-06712     tli driver: 인수시 오류
ora-06713     tli driver: 연결시 오류
ora-06720     tli driver: sid 찾기 실패
ora-06721     tli driver: 가 클라이언트 요구
ora-06722     tli driver: 연결설정 실패
ora-06730     tli driver: 크론(clone) 디바이스의 열기 실패
ora-06731     tli driver: t_call을 할당할 수 없습니다.
ora-06732     tli driver: t_discon을 할당할 수 없습니다.
ora-06733     tli driver: 분리 수신에 실패했습니다.
ora-06734     tli driver: 연결할 수 없습니다.
ora-06735     tli driver: 잘못된 연결을 닫는데 실패했습니다.
ora-06736     tli driver: 서버가 가동중이 아닙니다.
ora-06737     tli driver: 연결실패
ora-06741     tli driver: 프로토콜 디바이스를 열 수 없습니다.
ora-06742     tli driver: t_bind를 할당할 수 없습니다.
ora-06743     tli driver: t_bind를 할당할 수 없습니다.
ora-06744     tli driver: 리스너(listener)를 바인드할 수 없습니다.
ora-06745     tli driver: 리스너(listener)가 이미 가동중입니다.
ora-06746     tli driver: t_call을 할당할 수 없습니다.
ora-06747     tli driver: 청취(listen) 오류
ora-06748     tli driver: t_discon을 할당할 수 없습니다.
ora-06749     tli driver: 네트워크상에서 옵션이 허용되지 않습니다.
ora-06750     tli driver: sync 실패
ora-06751     tli driver: 번지 범위가 다릅니다.
ora-06752     tli: 시그널 설정시 오류
ora-06753     tli driver: name-to-address를 맹핑하는데 실패했습니다.
ora-06754     tli driver: 지역 호스트 번지를 얻을 수 없습니다.
ora-06755     tli driver: 이동 마감점을 닫을 수 없습니다.
ora-06756     tli driver: oratab을 열 수 없습니다.
ora-06757     tli driver: 서버가 틀린 명령을 취했습니다.
ora-06760     tli driver: 순차릴리스를 읽는 동안 타임아웃됐습니다.
ora-06761     tli driver: 순차릴리스의 송신오류
ora-06762     tli driver: 순차릴리스의 읽기오류
ora-06763     tli driver: 분리 송신오류
ora-06764     tli driver: 분리 읽기오류
ora-06765     tli driver: 순차 릴리즈의 대기오류
ora-06766     tli driver: 릴리스시 닫기실패
ora-06767     tli driver: 릴리즈시 할당실패
ora-06770     tli driver: 버전 송신오류
ora-06771     tli driver: 버전 읽기오류
ora-06772     tli driver: 명령 송신오류
ora-06773     tli driver: 명령 읽기오류
ora-06774     tli driver: 브레이크 모드 송신오류
ora-06775     tli driver: 브레이크 모드 읽기오류
ora-06776     tli driver: 파라미터 송신오류
ora-06777     tli driver: 파라미터 읽기오류
ora-06778     tli driver: ccode 송신오류
Posted by 1010
02.Oracle/DataBase2008. 11. 17. 14:33
반응형

ora-00257
: archiver error

위 오류는 해당 디스크에 더이상 아카이브 로그가 쌓일 공간이 없을 때 발생할 가능성이 매우 높다
Posted by 1010
60.Unix2008. 11. 14. 15:36
반응형

시스템을 부팅시켰는데, root 암호를 모른다면?



1. stop + a
키를 눌러서 시스템을 ok 상태로 shutdown을 시킵니다
.

2. CD
를 넣고, CD-ROM으로 single booting을 수행


root
의 암호를 모르기 때문에 OS가 설치되어 있는 disk로 수행하면 소용이 없어요
.

간혹, disk single booting을 수행하시는 분이 있는데, 그건 리눅스 얘기겠죠
??


ok boot cdrom -s

3. disk
에 저장되어 있는 /etc/shadow 파일을 읽어들이기 위해서 root device


mount
해야 하는데, stop + a 키를 눌러서 시스템을 shutdown 시킨 경우에는


파일 시스템이 깨지는 경우가 많으므로, mount를 하기 전에 먼저 root device에 대한


파일 시스템을 체크해줘야 한다는걸...다들 아시죠
?? ^^*



# fsck /dev/rdsk/c0t0d0s0 ( / device
logical device name을 사용
)


4.
파일 시스템 체크가 끝났으면, root device CD-ROM의 임시 디렉토리인 /a


mount
를 수행




# mount /dev/dsk/c0t0d0s0 /a


5.
여기까지 하게되면, root device로 접근이 가능하겠죠
?

그럼, vi 통해서 /a/etc/shadow 파일을 편집을 하면 되는데, 이때, CD-ROM으로


single booting
을 수행하면, terminal type이 잘 맞지를 않아서, 화면이 깨져서 나타나게


됩니다
.

vi
편집기를 제대로 사용하기 위해서, TERM 이라는 변수를 이용해서 terminal type


맞춰주어야 합니다
.



# TERM=sun ; export TERM


6. terminal setting
이 끝났다면, vi /a/etc/shadow 파일을 열어서 root의 암호 부분을


지워주시면 되겠죠
?

그런후에 강제로 저장... 이유는 read-only 파일이기 때문이죠
..^^;



# vi /a/etc/shadow



root:imDcKVUmwoRHc:12396::::::


바로 위의 빨간색 부분을 삭제하신후 저장하시면 됩니다
..^^*


7.
저장이 끝났으면, mount해서 사용하던 root device mount를 해제합니다
.


# umount /a


8.
시스템을 rebooting 한후, root로 로그인을 할때 root 암호를 묻지 않고 로그인 가능


root
로 로그인후, 반드시 root 암호를 새로이 부여해야겠죠
?



# reboot
Posted by 1010
60.Unix2008. 11. 14. 11:35
반응형

1.8139랜카드 인스톨후 재부팅 
2./etc/hostname.rtls0 이름 
3./etc/hosts 사설아이피 이름 loghost 
4./etc/defaultrouter 192.168.0.1 
5./etc/nsswitch.conf  dns 추가 
6./etc/resolv.conf  domain hananet.net 2개의nameserver IP 
7.ifconfig rtls0 down 
8.ifconfig rtls0 plumb 
9.ifconfig rtls0 IP netmask 255.255.255.0 broadcast + up 
10.rtls1에대해 똑같이 해주고 
11.route add default 192.168.0.1 

실제예
1) ifconfig rtls0 125.140.110.124 netmask 255.0.0.0 broadcast 125.140.110.255
2) vi /etc/hosts (chmod 644 /etc/hosts 하여 쓰기 권한을 준다.)
   # internet host table
   127.0.0.1   localhost
    :: 1    localhost
    125.140.110.123  mains  loghost
:wq!

3) vi /etc/resolv.conf
    nameserver 168.126.63.1
    nameserver 168.125.63.2
:wq!

4) route add default 125.140.110.1
5) route flush (확인)
6) ifconfig -a (네트워크 셋팅 전체 확인)
Posted by 1010
05.JSP2008. 11. 13. 15:29
반응형

<%-- requestSession.jsp --%>
%@page import="java.util.*" contentType="text/html;charset=euc-kr"%

<HTML><HEAD><TITLE>세션과 쿠키정보</TITLE></HEAD>

<BODY style="font-size:9pt">
<H3> 세션 정보출력</H3>
<%
         HttpSession sess = request.getSession(true);
         out.print("<b>[Requested Session유효여부]:</b>" +  request.isRequestedSessionIdValid() + "<BR>");
         out.print("<b>[Session 쿠키사용여부]:</b>" + request.isRequestedSessionIdFromCookie() + "<BR>");
         out.print("<b>[Session URL사용여부]:</b>" + request.isRequestedSessionIdFromURL() + "<BR>");
         out.print("<b>[Requested Session Id]:</b>" + request.getRequestedSessionId() + "<BR>");
         out.print("<b>[Session ID]:</b>" + sess.getId());
%>

<H3>쿠키정보출력</H3>
<%

         Cookie [] cookies = request.getCookies();
         for(int i = 0; i < cookies.length; i++) {
                  out.print("<b>" + cookies[i].getName() + "</b>: " + cookies[i].getValue());
         }
%>
</FONT></BODY></HTML>

Posted by 1010
61.Linux2008. 11. 13. 13:18
반응형

본 내용은 슈퍼유저코리아(http://www.superuser.co.kr)에서 발췌ㅤ한 내용으로 약간의 수정을 하였습니다.

우선 설치되어 있는지 확인합니다.
rpm -qa | grep vsftpd

설치되어 있지 않을 경우 아래와 같이 설치합니다.

1. 설치
    yum install vsftpd (Redhat은 설치파일을 다운로드 받는데 Fedora는 정말 편하네요)

2. 설정
    FTP서비스 시작 : /etc/rc.d/init.d/vsftpd start
    FTP서비스 종료 : /etc/rc.d/init.d/vsftpd stop
    부팅시 자동 실행 : chkconfig vsftpd on
    설정파일 : /etc/vsftpd/vsftpd.conf
   
    01) 아스키 모드로 설정하려면
         ascii_download_enable = YES
         ascii_upload_enable = YES
         로 설정합니다.
    02) 쉘권한이 없는 사용자들이 FTP를 사용하게 하려면..
         /etc/pam.d/vsftpd 파일 4번째줄 앞에 # 을 입력하여 주석처리합니다.
         #%PAM-1.0
         auth     required    pam_listfile.so item=user sense=deny file=/etc/vsftpd.ftpusers
         onerr=succeed
         auth     required    pam_stack.so service=system-auth
         #auth    required    pam_shells.so
         account    required    pam_stack.so service=system-auth
         session    required    pam_stack.so service=system-auth

    03) home디렉토리 상위로 이동금지
         chroot_list_enable=YES
         chroot_local_user=YES
         설정후 접속할 때 /etc/vsftpd.chroot_list 파일이 없다는 오류가 발생하게 되면, 해당파일을
         생성해줍니다. 제외계정명을 해당파일에 넣어줍니다.
  
    04) 숨김파일을 보이게 하려면..(서버상에서 설정)
         보통 파일명이나 폴더명앞에 "."이 있는경우 숨김파일로 됩니다. 이를 보이도록 설정합니다.
         force_dot_files=YES

    05) FTP접속시 소유권숨기기
         hide_ids=YES

    06) ls -R 명령 허용하기
         ls_recurse_enable=YES
 
    07) openssh에 chroot패치된것을 같이 사용하기
         passwd_chroot_enable=YES

    08) 시간이 잘못 표현될 때
         use_localtime=YES

    09) 전송속도를 제한할 때
         local_max_rate=300000  (숫자의 단위는 Bytes/Sec)

    10) 동시 접속자수 제한
         max_clients=10  (숫자만큼 제한)

    11) IP당 접속자수 제한
         max_per_ip=2 (수자만큼 제한)

    12) PASSIVE모드 사용시 포트 범위 제한
         PASSIVE모드는 일반 20번 포트를 방화벽때문에 사용하지 못할때 사용하는 모드입니다.
         pasv_min_port=40000
         pasv_max_port=50000
         (40000 ~ 50000 으로 PASSIVE포트 제한)
 
    13) 확장자의 업로드 금지
         deny_file={*.확장자,*.확장자}

    14) 특정파일 숨기기
         hide_file={*.확장자,.hide,hide*.h?}
Posted by 1010
반응형

잡지 표지를 만들어주는 사이트

http://www.magmypic.com/

Posted by 1010
06.Ajax2008. 11. 13. 11:42
반응형

=============================================================================
====== Ajax 관련 자주 방문해야 하는 싸이트 ========
=============================================================================
 
 
 
 
 
 
 
 
 
 
 
=============================================================================
====================== Ajax 관련 오픈소스=======================
=============================================================================
=============================================================================
=============== Ajax 관련 라이브러리 & 툴 =================
=============================================================================
http://www.youngpup.net/2001/domdrag/ => dom dram 관련 싸이트
 
IBM AJAX Toolkit Framework =>IBM AJAX Toolkit Framework
An Eclipse Incubation Project Proposal =>IBM AJAX Toolkit Framework을 이해하는데 도움을 주는 제안서
 
http://httpunit.sourceforge.net/ => HttpUnit 테스팅 프레임웍
 
http://fitnesse.org/ => FitNesse 테스팅 프레임웍
 
http://jwebunit.sourceforge.net/ => 웹 테스팅 프레임웍으로 자바 개바자라면 추천해 본다.

http://www.edwardh.com/jsunit/ => JsUnit 홈페이지


http://devedge-temp.mozilla.org/toolbox/examples/2003/inheritFrom/index_en.html => 넷스케이프 커뮤니케이션의 Bob Clay 는 부모 클래스의 메소드를 자식 클래스에 복사할 수 있는 아주 간단한 메소드를 소개하였다.


http://chrispederick.com/work/webdeveloper/ => Web Developer Extension for FireFox 으로써 파이어폭스 브라우저가 제공해 주는 다양한 기능의 툴바를 다운/설치할 수 있는 싸이트이다.


http://hometown.aol.de/_ht_a/memtronic/ => 자바스크립트 파일을 압축하거나 Obfuscation(자신의 소스코드를 다른 사람이 악의적으로 도용하고나 훔쳐가는 것을 막기 위해서 멤버나 메소드 이름을 의미없는 문자들로 바꾸는 기법)하는 Freeware 싸이트이나 현재버젼에서는 아직까지 자바스크립트에 대한 Obfuscation 은 지원하지 않고 있다.


http://www.jslint.com/ => 자바스크립트 소스코드를 검증해 주는 싸이트


http://www.mozilla.com/ => 모질라 닷컴/파이어 폭스 최신버젼 다운로드


https://addons.mozilla.org/ => FireFox add on home page


https://addons.mozilla.org/extensions/?application=firefox => firefox add on extensions


http://www.activeperl.com/ => 펄의 런타임 환경인 ActivePerl 을 다운로드 받을 수 있다.


http://jsdoc.sourceforge.net/ => javadoc 명령으로 HTML API를 생성하듯이 자바스크립트의 주석을 바탕으로 HTML 다큐먼트를 생성하는 오픈소스


http://www.openqa.org/selenium/ => html 및 자바스크립트를 검사해주는 아주 훌륭한 오픈소스다. 실험적인 프로그램이지만 100점 주고 싶다.


http://www.activeperl.com/ => 펄 런타임 환경 다운로드 싸이트


http://jsdoc.sourceforge.net/ => jsDoc


http://www.json.org => JSON 홈페이지


http://www.ashleyit.com/rs/main.htm => Remote Scripting 관련하여 Brent Ashley 가 운영하는 싸이트




=============================================================================

======================= Ajax 응용 싸이트 =========================
=============================================================================
 
=> 구굴에서 만든 달력 및 메모
 
http://maps.a9.com/ => Ajax 를 이용한 map 싸이트
 

http://maps.google.com/ => 구굴 맵


http://www.google.com/ig => Draggable DOM pattern 을 아주 훌륭하게 적용한 싸이트


http://www.google.com/webhp?complete=1&hl=kor => 구굴 Suggest 한글 검색창


http://www.google.com/webhp?complete=1&hl=en => 구굴 Suggest 영문 검색창


http://www.netflix.com/BrowseSelection => ajax 를 이용한 툴팁을 구현한 싸이트


http://www.apple.com/itunes/ => AJAX 관련 refresh 기능을 구현해 놓은 싸이트.(애플 itunes 뮤직 다운로드 자동 카운트)


http://www.digg.com/spy => AJAX 관련 refresh 기능을 구현해 놓은 싸이트.(새로운 정보 컨텐츠 리스트 자동 소팅 기능)

 
 
 

=============================================================================

============== Ajax 관련  기타  참고 싸이트 ==============
=============================================================================

http://www.apress.com/book/supplementDownload.html?bID=10042&sID=3021 => Foundation of Ajax 소스 다운로드 url



|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

출처: http://blog.naver.com/jinoxst/140021466351 


 

AJAX 관련 자주 방문해야 하는 싸이트


http://ajaxian.com/


http://ajaxpatterns.org


http://ajaxmatters.com/r/welcome


http://ajaxblog.com/


http://labs.google.com/


http://www.adaptivepath.com/


http://www.37signals.com/


http://www.oreilly.com/


http://developer.apple.com/



AJAX 관련 오픈소스


http://zk1.sourceforge.net/


http://sourceforge.net/projects/zk1/


http://sourceforge.net/projects/taconite


http://www.rubyonrails.org/


http://www.ruby-lang.org/en/


http://swik.net/AJAXSLT


http://code.google.com/webtoolkit/



AJAX 관련 라이브러리 & 툴


http://www-128.ibm.com/developerworks/kr/library/os-ecl-ajax/
=> Eclipse의 Ajax Toolkit Framework에서 지원되는 툴 (한글)


http://www.youngpup.net/2001/domdrag/
=> dom dram 관련 싸이트


http://httpunit.sourceforge.net/
=> HttpUnit 테스팅 프레임웍


http://fitnesse.org/
=> FitNesse 테스팅 프레임웍


http://jwebunit.sourceforge.net/
=> 웹 테스팅 프레임웍으로 자바 개바자라면 추천해 본다.


http://www.edwardh.com/jsunit/

=> JsUnit 홈페이지


http://devedge-temp.mozilla.org/toolbox/examples/2003/inheritFrom/index_en.html

=> 넷스케이프 커뮤니케이션의 Bob Clay 는 부모 클래스의 메소드를 자식 클래스에 복사할 수 있는 아주 간단한 메소드를 소개하였다.


http://chrispederick.com/work/webdeveloper/

=> Web Developer Extension for FireFox 으로써 파이어폭스 브라우저가 제공해 주는 다양한 기능의 툴바를 다운/설치할 수 있는 싸이트이다.


http://hometown.aol.de/_ht_a/memtronic/

=> 자바스크립트 파일을 압축하거나 Obfuscation(자신의 소스코드를 다른 사람이 악의적으로 도용하고나 훔쳐가는 것을 막기 위해서 멤버나 메소드 이름을 의미없는 문자들로 바꾸는 기법)하는 Freeware 싸이트이나 현재버젼에서는 아직까지 자바스크립트에 대한 Obfuscation 은 지원하지 않고 있다.


http://www.jslint.com/

=> 자바스크립트 소스코드를 검증해 주는 싸이트


http://www.mozilla.com/

=> 모질라 닷컴/파이어 폭스 최신버젼 다운로드


https://addons.mozilla.org/

=> FireFox add on home page


https://addons.mozilla.org/extensions/?application=firefox

=> firefox add on extensions


http://www.activeperl.com/

=> 펄의 런타임 환경인 ActivePerl 을 다운로드 받을 수 있다.


http://jsdoc.sourceforge.net/

=> javadoc 명령으로 HTML API를 생성하듯이 자바스크립트의 주석을 바탕으로 HTML 다큐먼트를 생성하는 오픈소스


http://www.openqa.org/selenium/

=> html 및 자바스크립트를 검사해주는 아주 훌륭한 오픈소스다. 실험적인 프로그램이지만 100점 주고 싶다.


http://www.activeperl.com/

=> 펄 런타임 환경 다운로드 싸이트


http://jsdoc.sourceforge.net/

=> jsDoc


http://www.json.org

=> JSON 홈페이지


http://www.ashleyit.com/rs/main.htm

=> Remote Scripting 관련하여 Brent Ashley 가 운영하는 싸이트



AJAX 응용 싸이트


http://www.dhteumeuleu.com/

http://www.google.com/calendar/render
=> 구굴에서 만든 달력 및 메모

http://maps.a9.com/
=> Ajax 를 이용한 map 싸이트

http://maps.google.com/

=> 구굴 맵


http://www.google.com/ig

=> Draggable DOM pattern 을 아주 훌륭하게 적용한 싸이트


http://www.google.com/webhp?complete=1&hl=kor

=> 구굴 Suggest 한글 검색창


http://www.google.com/webhp?complete=1&hl=en

=> 구굴 Suggest 영문 검색창


http://www.netflix.com/BrowseSelection

=> ajax 를 이용한 툴팁을 구현한 싸이트


http://www.apple.com/itunes/ =

> AJAX 관련 refresh 기능을 구현해 놓은 싸이트.(애플 itunes 뮤직 다운로드 자동 카운트)


http://www.digg.com/spy

=> AJAX 관련 refresh 기능을 구현해 놓은 싸이트.(새로운 정보 컨텐츠 리스트 자동 소팅 기능)


AJAX 관련  기타  참고 싸이트

http://www.apress.com/book/supplementDownload.html?bID=10042&sID=3021

=> Foundation of Ajax 소스 다운로드 url

Posted by 1010
91..개발관련프로그램2008. 11. 13. 11:42
반응형

http://ietoy.net/

네이버나...머나..필요한 자료를 찾아도 마우스 드래그가 안되어서 필요할때마다 찾아야 하는 번거로움이 있을 것이다.

이때..이넘을 설치하고 마우스 오른쪽을 클릭하고 드래그 하면...된다.--a


설치법
 1. 첨부파일을 다운받아서 찾기 쉬운 곳에 압축을 푸세요.
    (찾기쉬운 곳을 바탕화면이라 하겠습니다.)
 
 2. 압축푸신 폴더를 열고.(제 컴퓨터로는..C:\Documents and Settings\edward\바탕 화면\ietoy )
       '_install.bat'로 설치를 하시면 됩니다. 그리고 ietoy폴더는 삭제하시지 마세요.
 
 3. 모니터 오른쪽 아래에 ietoy라는 이미지가 등록되었다면 설치가 된겁니다.
    만약 설치가 안되었다면(컴퓨터 환경에 따라 안될수도 있어요.),
     'ietoy.exe'로 직접 실행시키시면, 오른? 아래에 이모티콘이 등록될겁니다.
 
 3.1. 'ietoy.exe'로 실행시 윈도우 시작시 바로 실행하게끔 하려면,
        오른쪽 아래 ietoy이모티콘에 마우스를 대시고 오른쪽을 클릭하고 '환경설정'을 클릭합니다.
        창이 하나 뜨고 왼쪽 위에 일반 탭 선택후  'window 시작시아토실행' 선택을 해 줍니다.
       (이미 되어있다면 패스)
 
사용법
다음 과정없이 사용하셔도 되지만..가끔 안될때를 위해.
 단 화면 하단 시스템 트레이에 이넘이 있어야 합니다.
 
 1. 좋은 자료들을 복사하려고 하는데..마우스로 선택이 안되게 해둔 사이트들을 발견.
     복사하려고 드래그를 하니...이건뭐..안됨..
 2. 해당 페이지 아무곳이나 마우스 오른쪽을 클릭.
 3. 다시 1번 과정 실행.  선택 가능..복사 가능..^^;;
Posted by 1010
91..개발관련프로그램2008. 11. 13. 11:40
반응형
http://www.eclipseplugincentral.com/

실제로 사용중인 것은 몇개 없겠지만..

많다 ~~~


사용자 삽입 이미지
Posted by 1010
반응형

http://labs.adobe.com/wiki/index.php/Flex_3:Applications#Dashboard

FLEX 3.0 예제 샘플 DashBoard ---> 유용하게 써먹을 수 있을 것 같다

http://flex.org/components/ ->역시 유용
http://www.alex-uhlmann.de/flash/adobe/blog/distortionEffects/effectCube/ -> open source effect Good~
Posted by 1010
54.iBATIS, MyBatis/iBatis2008. 11. 13. 11:28
반응형

<펌글:http://blog.paran.com/devtopia/13828096>

실무에서 SQL문을 작성하다 보면 동적인 쿼리문 작성을 작성해야 할 때가 많이 있다.

이때 지겹게 if~else if 문을 통해 아주 지저분한 소스 코드를 생성할 때가 왕왕 있게 마련이다.

이때 ibatis에서는 아주 깔금하게 구현할 수 있는 방법을 제공해 준다.


<statement id="dynamicGetAccountList" resultMap="account-result">

  select * from account

  <dynamic prepend="WHERE">

    <isNotNull prepend="AND" property="firstName">

      (acc_first_name = #firstName#

    <isNotNull prepend="OR" property="lastName">

       acc_last_name = #lastName#

    </isNotNull>

    )

    </isNotNull>

    <isNotNull prepend="AND" property="emailAddress">

      acc_email like #emailAddress#

    </isNotNull>

    <isGreaterThan prepend="AND" property="id" campareValue="0">

      acc_id = #id#

    </isGreaterThan>

  </dynamic>

  order by acc_last_name

</statement>


상황에 의존적인 위 동적 statement로 부터 각각 다른 16가지의 SQL문이 생성될 수 있다. if-else구조와 문자열 연결을 코딩하는 경우 수백라인이 필요할 수도 있다.

동적 statement를 사용하는 것은 몇몇 조건적인 태그를 추가하는 것처럼 간단하게 작성할 수 있다.


이러한 조건들에 대해 간단히 정리하면 아래와 같다.


바이너리 조건 요소-바이너리 조건 요소는 정적값 또는 다른 프로퍼티값을 위한 프로퍼티값과 비교한다. 만약 결과가 true라면 몸체부분의 SQL쿼리가 포함된다.


바이너리 조건 속성

prepend

Statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

property

비교되는 property(필수)

compareProperty

비교되는 다른 property (필수 또는 compareValue)

compareValue

비교되는 값(필수 또는 compareProperty)


<isEqual>

프로퍼티가 값 또는 다른 프로퍼티가 같은지 체크

<isNotEqual>

프로퍼티가 값 또는 다른 프로퍼티가 같지 않은지 체크

<isGreaterThan>

프로퍼티가 값 또는 다른 프로퍼티 보다 큰지 체크

<isGreaterEqual>

프로퍼티가 값 또는 다른 프로퍼티 보다 크거나 같은지 체크

<isLessThan>

프로퍼티가 값 또는 다른 프로퍼티 보다 작은지 체크

<isLessEqual>

프로퍼티가 값 또는 다른 프로퍼티 보다 작거나 같은지 체크


사용법 예제)

<isLessEqual prepend="AND" property="age" compareValue="18">

  ADOLESCENT = 'TRUE'

</isLessEqual>


단일 조건 요소-단일 조건 요소는 특수한 조건을 위해 프로퍼티의 상태를 체크한다.

prepend

statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

property

체크하기 위한 프로퍼티(필수)

 

<isPropertyAvailable>

프로퍼티가 유효한지 체크

(이를 테면 파라미터의 프로퍼티이다.)

<isNotPropertyAvailable>

프로퍼티가 유효하지 않은지 체크

(이를 테면 파라미터의 프로퍼티가 아니다.)

<isNull>

프로퍼티가 null인지 체크

<isNotNull>

프로퍼티가 null이 아닌지 체크

<isEmpty>

Collection, 문자열 또는 String.valueOf() 프로퍼티가 null이거나 empty(“” or size() < 1)인지 체크

<isNotEmpty>

Collection, 문자열 또는 String.valueOf() 프로퍼티가 null 이아니거나 empty(“” or size() < 1)가 아닌지 체크


사용법 예제)

<isNotEmpty prepend="AND" property="firstName">

  FIRST_NAME = #firstName#

</isNotEmpty>


다른 요소들

Parameter Present : 파라미터 객체가 존재하는지 체크

Parameter Present Attributes : prepend - the statement에 붙을 오버라이딩 가능한 SQL부분

<isParameterPresent>

파라미터 객체가 존재(not null)하는지 체크

<isNotParameterPresent>

파라미터 객체가 존재하지(null) 않는지 체크

 

사용법 예제)

<isNotParameterPresent prepend="AND">

EMPLOYEE_TYPE = 'DEFAULT'

</isNotParameterPresent>


Iterate : 이 태그는 Collection을 반복하거나 리스트내 각각을 위해 몸체 부분을 반복한다.

Iterate Attributes :

  prepend - the statement에 붙을 오버라이딩 가능한 SQL부분 (옵션)

  property - 반복되기 위한 java.util.List타입의 프로퍼티 (필수)

  open - 반복의 전체를 열기 위한 문자열, 괄호를 위해 유용하다. (옵션)

  close - 반복의 전체를 닫기 위한 문자열, 괄호를 위해 유용하다. (옵션)

  conjunction - 각각의 반복 사이에 적용되기 위한 문자열, AND 그리고 OR을 위해 유용하다. (옵션)

<iterate>

java.util.List 타입의 프로퍼티 반복


사용법 예제)

<iterate prepend="AND" property="userNameList" open="(" close=")" conjunction="OR">

username = #userNameList[]#

</iterate>


주의:iterator요소를 사용할 때 리스트 프로퍼티의 끝에 중괄호[]를 포함하는 것은 중요하다. 중괄호는 문자열처럼 리스트를 간단하게 출력함으로부터 파서를 유지하기 위해 리스트처럼 객체를 구별한다.

Posted by 1010
반응형

Flex의 Visual Component(Box, Button, Application 등)은 기본적으로 UIComponent를 extends(상속)하여 만들어진다.

화면에 보여지는 컴포넌트라면 UIComponent를 extends하여 만들 것을 추천한다.

왜냐하면 기본적으로 잘 정리된 라이프 사이클(Life Cycle)로 구성되어 있어서 이를 잘 이용하면 쉽게 컴포넌트 하나를 만드는데 어려움이 없기 때문이다. 하지만 만약 개발자가 UIComponent에서 기본적으로 제공하는 라이프 사이클을 커스터마이징(Customize - 개인 또는 고객이 입맛에 맞게 만드는 것)해야 한다면 UIComponent가 아닌 Sprite나 DisplayObject를 extends하여 만들면 된다. 하지만 이때는 개발자가 많은 일을 해야한다.
(Naver Cafe FlexComponent 차카게님의 댓글 인용)

참고로 UIComponent는 다음과 같은 Class를 상속받아 만들어졌다.

UIComponent Inheritance FlexSprite Inheritance Sprite Inheritance DisplayObjectContainer Inheritance InteractiveObject Inheritance DisplayObject Inheritance EventDispatcher Inheritance Object

출처 : http://flexdocs.kr/docs/flex2/langref/m ··· ent.html

여기에 SpriteDisplayObject가 있다는 것을 확인하길 바란다. 참고로 각종 Event를 Dispatch(송출)해야하므로 EventDispatcher를 extends했다는 것도 확인할 수 있다.

이 글은 비주얼 컴포넌트가 기동시에 Event 및 method가 실행되는 시점을 분석하여 컴포넌트의 라이브 사이클을 알아내고 확장컴포넌트를 만드는데 필요한 지식을 얻는 것을 목표로 하고 있다.


1. 컴포넌트 기동시 송출(dispatch)되는 Event 분석


UIComponent 및 UIComponent를 extends한 컴포넌트는 기동시 아래와 같은 이벤트를 송출한다.

사용자 삽입 이미지

그림 1


이를 확인하기 위해 아래와 같은 코드로 확인해볼 수 있다.

ExLifeCycle.mxml (Language : xml)
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    preinitialize="traceEvent(event)"
    initialize="traceEvent(event)"
    creationComplete="traceEvent(event)"
    updateComplete="traceEvent(event)">

    <mx:Script>
        <![CDATA[
            private function traceEvent(event:Event):void
            {
                trace(event.currentTarget + " - " + event.type );
            }
        ]]>

    </mx:Script>
</mx:Application>

결과는 Debug모드에 Console 창에서 아래와 같이 나온다.
ExLifeCycle0 - preinitialize
ExLifeCycle0 - initialize
ExLifeCycle0 - creationComplete
ExLifeCycle0 - updateComplete
그럼 각 이벤트에 대해서 간단하게 설명하겠다.
  1. preinitialize - UIComponent에 정의된 initialize() 메소드가 호출되면 preinitialize 이벤트를 송출한다. 개발자가 내부구조를 작성하기 전에 컴포넌트를 변경하고 싶을때 preinitialize 이벤트에 대한 Listener를 작성해서 사용한다. 말그대로 가장 최초에 해야할 작업이 있을때 사용하면 된다.
    참고로 initialize() 메소드는 컴포넌트의 부모의 addChild() 및 addChildAt() 메소드을 통해 자식으로 등록이 될 때 자동적으로 호출되는 함수이다. initialize() 메소드에 대한 자세한 내용은 http://flexdocs.kr/docs/flex2/langref/m ··· itialize 를 참고한다.
  2. initialize - UIComponent의 initialize()메소드에서 내부적으로 처리해야하는 사항들(자식만들기,속성값정의,사이즈정의,그림그리기등)을 모두 처리할 수 있도록 한 뒤 initialize 이벤트를 송출한다. 컴포넌트의 레이아웃전에 추가 처리가 필요한 경우 이 이벤트를 사용한다.
  3. creationComplete - 컴포넌트 구축, 속성처리, 측정, 레이아웃 및 그림그리기가 모두 완료되었을때 송출된다. 이 이벤트는 컴포넌트 생성시 단 한번만 호출된다.
  4. updateComplete - 내부적으로 commitProperties(), measure(), updateDisplayList() 메소드을 호출함으로 인해 컴포넌트의 레이아웃, 위치, 사이즈등의 시각적 특징이 변경되어 컴포넌트의 화면상 모습이 갱신될때마다 송출된다.
이 이벤트들의 특성을 잘 파악하고 쓸 필요가 있다. 만약 Button컴포넌트를 생성되기도 전에 width와 height를 참고할려고 하면 그 값은 모두 0인 경우가 있다. 이런 경우에는 creationComplete 이벤트를 받아 처리하면 쉽게 해결할 수 있을것이다. 또 버튼이 그려지기 전에 동적으로 값을 설정할 필요가 있는 경우 preinitialize 이벤트를 받아 처리한다. 물론 Button 조차 동적으로 생성하는 경우에는 부모에 addChild()함수등으로 인해 자식으로 포함되기전 관련 작업을 해도 되겠다. 왜냐하면 addChild한 뒤에 initialize()함수가 호출이 되기 때문이다.


2. 컨테이너와 자식 컴포넌트 기동시 Event 송출 흐름 분석

여기서 말하는 컨테이너는 Application, Canvas, Box등이 그것이다. 자식으로 Component는 Button, ComboBox등이 되겠다. 아래 그림을 보자. 그림은 컨테이너가 자식컴포넌트를 가질때 발생하는 Event에 대해 잘 묘사하고 있다.

사용자 삽입 이미지

그림 2. 컨테이너에 속한 라이프사이클중에 Dispatch(송출)되는 주요 이벤트


전체적인 흐름은 그림 1 과 다른 것이 없다. 추가 및 변경 되는 사항은 컨테이너에 childAdd Event가 추가되었다는 것과 부모와 자식간에 Event 송출시점이 다르다는 점이다. 이런 Event흐름을 가질 수 밖에 없는 것은 앞에서 Event의 특성을 생각해보면 쉽게 유추할 수 있다. 참고로 만약 컨테이너가 Application인 경우엔 마지막에 applicationComplete Event가 송출된다.

다음은 위의 이벤트 흐름을 확인하기 위한 예제 코드이다.
(FlexComponent카페 브라이언님의 예제를 참고하였다. http://cafe.naver.com/flexcomponent/1200)

ExLifeCycle.mxml (Language : xml)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    add="traceEvent(event)"
    added="traceEvent(event)"
    preinitialize="traceEvent(event)"
    initialize="traceEvent(event)"
    childAdd="traceEvent(event)"
    creationComplete="traceEvent(event)"
    updateComplete="traceEvent(event)"
    applicationComplete="traceEvent(event)">

    <mx:Script>
        <![CDATA[
            private function traceEvent(event:Event):void
            {
                trace(event.type+"("+ event.eventPhase + ") " + event.currentTarget.name + " " + event.target.name + "   " + event.target.parent.name  );
            }
        ]]>

    </mx:Script>
    <mx:Button id="button"
            add="traceEvent(event)"
            added="traceEvent(event)"
            preinitialize="traceEvent(event)"
            initialize="traceEvent(event)"
            creationComplete="traceEvent(event);"
            updateComplete="traceEvent(event)"/>

</mx:Application>


결과는 Debug모드에서 실행하면 Console 창에서 아래와 같이 확인할 수 있다.
이벤트 Type(Phase) currentTarget target target.parent
added(3) ExLifeCycle0 border ExLifeCycle0
add(2) ExLifeCycle0 ExLifeCycle0 root1
preinitialize(2) ExLifeCycle0 ExLifeCycle0 root1
added(2) button button ExLifeCycle0
added(3) ExLifeCycle0 button ExLifeCycle0
childAdd(2) ExLifeCycle0 ExLifeCycle0 root1
add(2) button button ExLifeCycle0
preinitialize(2) button button ExLifeCycle0
added(3) button UITextField5 button
added(3) ExLifeCycle0 UITextField5 button
initialize(2) button button ExLifeCycle0
initialize(2) ExLifeCycle0 ExLifeCycle0 root1
added(3) button upSkin button
added(3) ExLifeCycle0 upSkin button
added(3) ExLifeCycle0 backgroundMask ExLifeCycle0
added(3) ExLifeCycle0 ApplicationBackground7 ExLifeCycle0
creationComplete(2) button button ExLifeCycle0
updateComplete(2) button button ExLifeCycle0
creationComplete(2) ExLifeCycle0 ExLifeCycle0 root1
added(2) ExLifeCycle0 ExLifeCycle0 root1
applicationComplete(2) ExLifeCycle0 ExLifeCycle0 root1
updateComplete(2) ExLifeCycle0 ExLifeCycle0 root1
Phase
(위상-이벤트흐름단계)
1 : Capture단계
2 : target단계
3 : bubble 단계


아래 그림 3은 위 프로그램의 부모 자식관계를 표현하고 있다. 우리는 인위적으로 Application에 button만 컴포넌트로 추가했다. 하지만 target을 보면 Application은 child로 border, backgroundMask, ApplicationBackground를 가지는 것과 button은 child로 UITextField와 upSkin을 가진다는 것을 확인할 수 있다. 위의 결과에서 added Event와 add Event만 뺀다면 그림 2 에서 보여준 Event 흐름과 다를 바 없다는 것을 확인할 수 있다.

사용자 삽입 이미지

그림 3. parent와 child관계

여기서 Event Listener를 Application과 Button에 만들었다. 다른 Event들과 다르게 added Event가 발생할 때는 자신 및 부모 컴포넌트에게도 Event가 전파되는 것을 확인할 수 있다. 즉, 부모컴포넌트인 button에 UITextField와 upSkin에서 발생한 added Event가 전파된다는 말이다. 이는 added Event송출시에 Event의 bubbles 인자가 true이기 때문이다. 구체적으로 설명하면 dispatchEvent( new Event( "added", true, false )) 형태로 Event의 2번째 인자를 true 로 설정해서 Event를 송출(Dispatch)한다. 그러므로 이벤트가 target단계뿐 아니라 bubble단계로 전파가 된다.

더욱 구체적인 살펴보기 위해, 위 결과에서 분홍색표시된 부분을 보자. button의 자식 컴포넌트인 UITextField는 added Event를 송출한다. added Event는 bubble단계도 전파하므로 target는 항상 UITextField이고 bubble(3)단계에서 UITextField의 부모인 button이 이 added Event를 listen하고 있으므로 currentTarget이 button일때 traceEvent()를 메소드를 실행하는 것을 볼 수 있다. 또 button의 부모인 Application에서도 added Event를 Listen하고 있으므로 currentTarget이 ExLifeCycle일때 traceEvent() 메소드를 실행하게 된다.

이것을 명확하게 이해하기 위해서는 currentTarget과 target이 뜻과 이벤트 전파방법(capture, target, bubble 단계)에 대해서 정확히 이해할 필요가 있다.
이벤트 전파에 관해서는 이벤트 전파(http://flexdocs.kr/docs/flex2/docs/00000475.html)를 참고한다.

아래 그림은 위 결과를 보기 쉽게 그림으로 표현한 것이다.
사용자 삽입 이미지

그림 4. 이벤트 전파 다이어그램




그럼, 여기서 새로 나온 Event인 add, added, childAdd 이벤트에 대해서 간단히 소개한다.

  1. add : Container.addChild(), Container.addChildAt()를 사용해서 컨테이너에 자식이 추가 될 때, mx.events.FlexEvent 객체 생성
  2. added : DisplayObjectContainer.addChild(), DisplacyObjectContainer.addChildAt() 을 사용해서 컨테이너에 자식이 추가될 때 flash.events.Event 객체 생성
  3. childAdd : addChild(), addChildAt()을 사용해서 자기 하위로 자식이 추가 완료되었을 때, 부모가 자식이 잘 추가되었는지 확인하기 위해 이 이벤트로 확인이 가능하다. mx.events.ChildExistenceChangedEvent 객체 생성


3. 비주얼 컴포넌트의 확장에 대해


이미 언급했듯이 대부분의 비주얼 컴포넌트가 UIComponent를 확장해서 만들었으므로 UIComponent가 기본적으로 어떤 순서에 의해 메소드가 호출되고 이벤트가 발생하는지 알아야, 이미 만들어진 컴포넌트(Button등)를 분석할 수 있고 더 나아가 확장한 고급 컴포넌트를 만드는데 도움이 될 것이라 생각한다. UIComponent를 확장한 컨테이너 및 컴포넌트의 Event 흐름은 이미 언급했으므로 이제는 관련 메소드를 언급할 차례이다.

UIComponent를 extends한 가장 간단한 컴포넌트는 다음과 같다.

MyComp.as (Language : java)
package
{
    import mx.core.UIComponent;

    public class MyComp extends UIComponent
    {
        public function MyComp()
        {
            trace("MyComp 생성자 호출");
        }
    }
}

이러한 형태는 UIComponet일 수 있고 이미 UIComponent를 extends해서 만든 Button, Box등을 extends해도 된다.

UIComponent는 이미 생성순서에 맞게 호출하거나 중간중간 새로운속성, 사이즈조정, 화면표시에 대해 작업할 수 있도록 재정의(override)가 가능한 메소드가 만들어져 있다. 이러한 메소드들을 직접호출하지 않는다.

대표적인 메소드는 다음과 같다.

  • commitProperties() : 컴포넌트의 속성(properties)를 일괄적으로 조정할 필요가 있을 때 사용한다.  addChild에 의해 부모에 추가되었을 때와 invalidateProperties() 메소드를 호출할때 자동적으로 실행된다. 만약 getter나 setter에 의해 설정된 속성들을 이 commitProperties()에서 처리할 수 있도록 하면 width와 height 또는 horizontalScrollPolicy와 horizontalScrollPosition과 같이 서로 연관성있는 속성을 한꺼번에 처리하여 작업의 중복을 무시할 수 있도록 만들 수 있다. 구현방법에 대해서는 commitProperties()메소드의 구현을 참고한다.
  • createChildren() : 컴포넌트에 다른 자식 컴포넌트를 addChild할 경우에 사용한다. 가령 새로 작성되는 컴포넌트에 자식 컴포넌트로 ComboBox와 TextInput를 사용해야한다면 이 메소드를 재정의하여 그 안에서 addChild 한다. 이 메소드는 컴포넌트가 parent에서 addChild할때 단 한번 호출된다. 구현방법은 createChildren() 메소드의 구현을 참고한다.
  • layoutChrome() : 이 메소드는 UIComponet를 extends한 Container에 정의된 메소드이다. 컨테이너의 경계선의 위치 및 사이즈를 설정할때 사용된다. addChild에 의해 parent에 추가되었을때와 invalidateDisplayList() 메소드를 실행시 호출되는 메소드이다. 상세한 내용은 layoutChrome() 메소드의 구현을 참조한다.
  • measure() : 컴포넌트의 default 폭과 높이, default 최소 폭과 높이를 설정할 경우 사용한다. 이 메소드를 이용하면 가령, 컴포넌트에서 표시에 필요한 텍스트 양, fontSize등에 의한 텍스트 스타일, 컴포턴트에 표시되는 이미지 사이즈, 컴포넌트의 Child측정 사이즈 또는 명시적 사이즈, 모든 경계선 및 간격 등을 계산하여 적절한 사이즈를 선택해 적용이 가능하다. 기본적으로 parent에서 addChild할때와 invalidateSize()메소드를 실행하며 호출된다. 상세한 것에 대하여는,measure() 메소드의 구현을 참조한다.
  • updateDisplayList() : 앞서 지정된 속성 및 스타일 설정에 근거하여 화면상에 자식 컴포넌트의 배치 및 사이즈를 조절하고 각종 스킨 및 그래픽을 묘사하는데 사용한다. 가령, 컴포넌트에 자식 컴포넌트가 있는 경우 이 메소드에서 move() 및 setActualSize() 메소드등을 호출하여 배치나 사이즈 조정을 한다. 또, 자식 컴포넌트가 없는 경우 graphic.drawRect()와 같은 메소드를 이용해 그림을 그릴 수 있다. 사이즈의 경우 width, height대신 인자로 넘어온 unscaledWidth와 unscaledHeight를 이용한다. addChild에 의해 parent에 추가되었을때와 invalidateDisplayList() 메소드를 실행시 호출된다. 상세한 것에 대하여는,updateDisplayList() 메소드의 구현을 참고한다.
위에서 메소드들을 살펴보았듯이 확장 컴포넌트를 만들때 필요에 따라 적절히 위 메소드들을 재정의해서 사용하는 것이 중요하겠다. 관련된 예제는 ModalText 컴포넌트의 작성을 참고한다.


4. 메소드 및 Event로 본 컴포넌트의 라이브 사이클

그럼 본래 목적으로 넘어오자. 앞서 Event의 발생순서와 비주얼 컴포넌트에서 제공하는 재정의 가능한 메소드를 설명했다. 각각의 호출되는 시점과 그 때 발생하는 Event를 확인해 보도록 하겠다.

먼저 Application과 Button 확장하여 아래와 같이 위에서 제시한 메소드들을 전부 재정의한다. 재정의된 메소드 내에는 언제 메소드가 호출되는지 확인하기 위해 trace()를 사용한다.

MyApplication.as (Language : java)
package
{
    import mx.core.Application;

    public class MyApplication extends Application
    {
        public function MyApplication()
        {
            trace("    MyApplication Constructor()");
        }
       
        override public function initialize():void
        {
            trace("    MyApplication initialize()");
            super.initialize();
        }
       
        override protected function createChildren():void
        {
            trace("    MyApplication createChildren()");
            super.createChildren();
        }
       
        override protected function commitProperties():void
        {
            trace("    MyApplication createProperties()");
            super.commitProperties();
        }
       
        override protected function measure():void
        {
            trace("    MyApplication measure()");
            super.measure();
        }
       
        override protected function layoutChrome(unscaledWidth:Number, unscaledHeight:Number):void
        {
            trace("    MyApplication layoutChrome()");
            super.layoutChrome(unscaledWidth, unscaledHeight);
        }
       
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            trace("    MyApplication updateDisplayList()");
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }      
    }
}


MyButton.as (Language : java)
package
{
    import mx.controls.Button;

    public class MyButton extends Button
    {
        public function MyButton()
        {
            trace("    MyButton Constructor()");
        }

        override public function initialize():void
        {
            trace("    MyButton initialize()");
            super.initialize();
        }
       
        override protected function createChildren():void
        {
            trace("    MyButton createChildren()");
            super.createChildren();
        }
       
        override protected function commitProperties():void
        {
            trace("    MyButton createProperties()");
            super.commitProperties();
        }
       
        override protected function measure():void
        {
            trace("    MyButton measure()");
            super.measure();
        }
       
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            trace("    MyButton updateDisplayList()");
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }      
    }
}

위에서 만든 두개의 컴포넌트를 아래와 같이 사용한다. 예전에 Application과 Button대신 새로 정의한 컴포넌트인 MyApplication과 MyButton을 사용한 것 밖에 다른 점이 없다.

ExLifeCycle.mxml (Language : xml)
<?xml version="1.0" encoding="utf-8"?>
<local:MyApplication
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:local="*"
    layout="absolute"
    add="traceEvent(event)"
    added="traceEvent(event)"
    preinitialize="traceEvent(event)"
    initialize="traceEvent(event)"
    childAdd="traceEvent(event)"
    creationComplete="traceEvent(event)"
    updateComplete="traceEvent(event)"
    applicationComplete="traceEvent(event)">
   
    <mx:Script>
        <![CDATA[
            private function traceEvent(event:Event):void
            {
                trace(event.type+"("+ event.eventPhase + ") " + event.currentTarget.name + " " + event.target.name + "    " + event.target.parent.name  );
            }
        ]]>

    </mx:Script>
    <local:MyButton id="button" label="Submit" 
                add="traceEvent(event)"
                added="traceEvent(event)"
                preinitialize="traceEvent(event)"
                initialize="traceEvent(event)"
                creationComplete="traceEvent(event)"
                updateComplete="traceEvent(event)"/>

</local:MyApplication>


 

결과는 다음과 같다.
이벤트Type(Phase) currentTarget target target.parent method
        MyApplication Constructor()
added(3) ExLifeCycle0 border ExLifeCycle0  
add(2) ExLifeCycle0 ExLifeCycle0 root1  
        MyApplication initialize()
preinitialize(2) ExLifeCycle0 ExLifeCycle0 root1  
        MyApplication createChildren()
        MyButton Constructor()
added(2) button button ExLifeCycle0  
added(3) ExLifeCycle0 button ExLifeCycle0  
childAdd(2) ExLifeCycle0 ExLifeCycle0 root1  
add(2) button button ExLifeCycle0  
        MyButton initialize()
preinitialize(2) button button ExLifeCycle0  
        MyButton createChildren()
added(3) button UITextField5 button  
added(3) ExLifeCycle0 UITextField5 button  
initialize(2) button button ExLifeCycle0  
initialize(2) ExLifeCycle0 ExLifeCycle0 root1  
        MyApplication commitProperties()
        MyButton commitProperties()
added(3) button upSkin button  
added(3) ExLifeCycle0 upSkin button  
        MyButton measure()
        MyApplication measure()
        MyApplication updateDisplayList()
        MyApplication layoutChrome()
added(3) ExLifeCycle0 backgroundMask ExLifeCycle0  
added(3) ExLifeCycle0 ApplicationBackground7 ExLifeCycle0  
        MyButton updateDisplayList()
creationComplete(2) button button ExLifeCycle0  
updateComplete(2) button button ExLifeCycle0  
creationComplete(2) ExLifeCycle0 ExLifeCycle0 root1  
added(2) ExLifeCycle0 ExLifeCycle0 root1  
applicationComplete(2) ExLifeCycle0 ExLifeCycle0 root1  
updateComplete(2) ExLifeCycle0 ExLifeCycle0 root1  
Phase
(위상-이벤트흐름단계)
1 : Capture단계
2 : target단계
3 : bubble 단계


아래 그림은 위 결과를 보기 쉽게 다이어그램으로 표시했다.

사용자 삽입 이미지

그림 5. 이벤트 전파 및 메소드 실행 시점 다이어그램


앞서 설명했듯이 initialize() 메소드는 컴포넌트의 부모 컴포넌트가 addChild할 때에 호출되며 처음에는 preinitialize 이벤드를 송출하고 creationChildren() 메소드를 수행한 다음 initialize 이벤트를 송출한다.  부모 컴포넌트인 경우 자식을 성공적으로 add하면 childAdd 이벤트를 송출한다.

measure(), layoutChrome(), updateDisplayList() 메소드는 initialize 이벤트가 송출된 다음에 호출이 되며 이 함수들이 모두 실행한 후에 creationComplete 이벤트와 updateComplete 이벤트가 발생하는 것을 확인할 수 있다.

이에 대해 조금더 이해하기 위해 컴포넌트의 인스턴스화 라이프 사이클에 대해를 참고하면 되겠다.


정리하며

비주얼 컴포넌트의 라이브 사이클을 메소드와 이벤트를 통해 이해하고 있으면 좀더 고급적인 컴포넌트를 작성하는데 도움이 된다. 내용을 이해하는 것이 그리 쉽지는 않을 것이라 생각한다. 하지만 Flex 컴포넌트를 이해하는데 매우 중요한 개념이므로 꼭 숙지할 필요가 있다.

내용도 많고, 시간을 너무 많이 소비하는 것 같고, 귀차니즘도 몰려오고 그래서 약간 내용의 부실함 가져온 것 같다. 아래 참고글들을 잘 읽어보고 이해 안가는 내용을 조금씩 습득했으면 한다.

앞으로 이와 관련되어 좋은 글이 많이 나왔으면 한다.
Posted by 1010
91..개발관련프로그램2008. 11. 13. 11:09
반응형

 

출처: 윈도우의 아쉬운 2프로를 채워주는 프리웨어 (http://www.choboweb.com/57)

주요 기능

  • 최대 20개까지 가상 데스크탑 관리
  • 관리하는 모든 가상 데스크탑을 전체화면으로 보기 (Full Screen Preview)
  • 맥의 Expose처럼 현재 가상 데스크탑의 열린 창을 한 눈에 보기 (Window Catalogue)
  • 가상 데스크탑 간의 윈도우를 드래그앤드랍으로 편하게 이동 (Desktop Preview)
  • 개별 데스크탑마다 해상도, 배경화면, 아이콘 투명도 등의 설정 가능 (Configure Desktops)
  • 거의 모든 작업에 단축키 지정 가능
  • Rule을 통해 특정 애플리케이션을 모든 데스크탑에서 공유하기 등의 설정 가능
  • 윈도우 창의 투명도 조절, 제목표시줄만 남기는 롤업, 트레이로 보내기 등의 부가 기능

이런 분에게 필수

  • 업무시간에 최대한 일에만 집중하고 싶으신 분
  • 맥의 Expose 기능이 부러웠던 분
  • 모니터 하나로 10개 부럽지 않게 쓰고 싶은 분
Posted by 1010
91..개발관련프로그램2008. 11. 13. 11:07
반응형

전에 DeskSpace 올려준적이 있는데 이건 기능이 더욱 막강하며 다양한 효과가 일품이네요

아래 스샷을 보면 알수 있듯이 기능으로 3D Cube, Window Exposer, 3D Desktop Explorer,

3D Destop Flip, 3D Desktop Carousel, 3D Desk Roll 기능을 지원하며 다이렉트X 9가 설치되어 있 어야 실행되며 현재의 기능을 봐서는 발전 가능성이 커 보이며 기능도 입맞에 하나씩 실행해보니 지루하지 않네요 창이 별도로 6개까지 만들어 지며 태스크바에 보이는것도 별도로 출력됩니다. 현재 스샷화면을 보면은 엑셀과 그림판, IE7창 다수로 실행시켜 둔겁니다. 특히 CPU에 큰 부담이 없고해서 괜찮게 보입니다. 메몰은 기능이 많은 만큼 41메가 정도 먹는데 기능에 비해서는 생각보다 많이 먹지는 않은것으로 보입니다.


기능키 소개

F7  스페이스와 유사한 기능
F8  가상화면 펼치기(플립) 기능

F9  익스포제

F11 큐브전환


Ctrl 키 + F8  가상화면 원형 기능

Ctrl 키 + 숫자키  해당 데스크탑 이동

추가로 => 옵션에서 세부적인 설정가능


영문판과 기타 몇개국어 지원하지만 한국어는 지원을 안해서 한글 패치가 나오기를 바랄뿐이며

기능이 많은 만큼 유료버전이며 트라이얼 버전을 받을수 있으며 무료사용시간도 100분정도

주어진다고 합니다.



최소사양

  • Microsoft Windows® XP™ or Windows® Vista™
  • 1.4 Ghz processor
  • 512 MB of RAM (1 GB recommended)
  • DirectX 9.0c
  • 3D accelerated video adapter with at least 64MB of video memory

    홈피 : http://www.cubedesktop.com/

    다운로드 : http://www.cubedesktop.com/downloads/cubedesktoptryout.exe



  • 사용자 삽입 이미지
    사용자 삽입 이미지
    사용자 삽입 이미지
    사용자 삽입 이미지
    사용자 삽입 이미지
    사용자 삽입 이미지
    사용자 삽입 이미지


    가상 모니터 갯수
    사용자 삽입 이미지



    가상 모니터 미리보기
    사용자 삽입 이미지

    리소스 점유율( 테스트 사양 : 모바일 T7200 2.0Ghz, 그래픽 X1600 256MB, 메몰 2GB )
    사용자 삽입 이미지

    프로세스 메몰 점유율
    사용자 삽입 이미지
    Posted by 1010
    91..개발관련프로그램2008. 11. 13. 11:04
    반응형

    가상 데스크탑을 만들어주어 창을 분류해서 사용할 수 있을것 같다.
    게다가 창 전환도 아주 멋지게 빙빙 돌아간다. (아래 캡쳐 사진)
    그리고 프리웨어입니다.


    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:40
    반응형

    Release 2.3.4 (JDK 1.5 Required)

    Developer Build

    Example Application

    Documentation

    Latest Documentation: Note that the documentation for iBATIS is updated very frequently, so it is possible (likely) that there is newer documentation available in the Subversion repository than what is listed here. If in doubt, check Subversion. The documentation in Subversion is in Open Office format. This link will show the very latest version of all iBATIS for Java documentation:

    Undocumented Stuff:Although we try to keep the documentation as up-to-date as possible, sometimes the software simply evolves faster than the docs. In these cases, we make a habit of listing the undocumented features on the wiki, here: Undocumented features.

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:29
    반응형
    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:27
    반응형

    iBATIS환경을 이해할 수 있도록 흐름도를 한번 그려 보자!

    이미지를 클릭하면 원본을 보실 수 있습니다.


    위의 그림에서 알 수 있듯이 sqlMapConfig.xml문서가 바로 환경 설정 파일임을 알 수 있을 것이다.

    이것은 load시 한번만 인식 되는데 그 부분이 바로 앞의 모든 예제들에서 클라이언트 부분에 다음과 같은 코드가 된다.


          Reader reader = Resources.getResourceAsReader("ex2/sqlMapConfig.xml");


    이때 transationManager요소와 sqlMap요소들을 인식하여  RDBMS와 SQL문을 관리하는 xml문서들이 인식된다.그리고


         SqlMapClient sqlMapper = SqlmapClientBuilder.buildSqlmapClient(reader);


    문장으로 인해 인식된 SQL문들을 관리하는 xml요소들이 모두 sqlMapper로 하나의 객체에 id가 키값이 되어 Map구조로

    담겨져 관리된다. qureryForList()와 같은 메서드를 통하여 지정된 id를 사용하면 테이블에 있는 자원들을 Emp.xml에 정의된

    resultMap이나 지정된 객체로 쉽게 받는다.


    특징
    iBATIS Hibernate JPA
    간단함
    가장 좋음
    좋음 좋음
    완벽한 객체 관계 매핑 평균 가장 좋음 가장 좋음
    데이터 모델 변경시 융통성 좋음 평균 평균
    복잡성
    가장 좋음 평균 평균
    SQL에 대한 의존성 좋음 평균 평균
    성능 가장 좋음 가장 좋음 N/A *
    다른 관계 데이터베이스에 대한 이식성 평균 가장 좋음 N/A *
    자바가 아닌 다른 플랫폼에 대한 이식성 가장 좋음 좋음 지원하지 않음
    커뮤니티 지원과 문서화 평균 좋음 좋음
    <표:http://blog.openframework.or.kr/50에서 펌>

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:24
    반응형

    지디넷코리아]iBATIS SQLMaps(이하 아이바티스)는 이미 국내외 많은 개발자들이 사용하고 있는 퍼시스턴스 계층의 프레임워크이다. 실제로 국내에서 가장 크다는 포털 사이트인 네이버와 다음도 아이바티스를 사용하고 있으며, 다른 업체들도 아이바티스를 그대로 사용하거나 약간 변형시킨 형태로 사용하고 있는 것으로 알고 있다. 특집 3부에서는 아이바티스의 특징과 활용법에 대해 알아본다.

    과거 ORM의 대표인 하이버네이트와 데이터 매퍼인 아이바티스 간에 어느 프레임워크가 더 좋은가에 대한 논쟁도 있었을 만큼 많은 자바 개발자들은 데이터베이스에 관련된 ORM 프레임워크에 대한 관심이 크다.

    이런 논쟁 가운데 아이바티스는 ORM이 아니기 때문에 논쟁의 대상이 될 수 없다는 의견도 있었다. 사용 목적이라는 관점에서 본다면 하이버네이트와 아이바티스는 논쟁의 대상이 될 수 있으나 ORM이냐 아니냐를 가름하는 관점에서 본다면, 역시 아이바티스는 ORM이 아니라고 할 수 있다.

      ORM과 데이터 매핑

    아이바티스의 핵심 개발자인 래리 메도스(Larry Meadors)는 다음처럼 ORM과 데이터 매퍼를 구분한다.

    ORM = 데이터베이스 객체를 자바 객체로 매핑
    Data mapping = SQL “구문”을 자바 객체로 매핑

    여기서 말하는 개념은 두 프레임워크의 성격을 제대로 이해할 수 있게 해준다. 이러한 개념적인 차이점은 결과적으로 ORM의 캐싱 전략은 데이터베이스 객체에 매핑 된 자바 객체가 캐시에 저장되는 게 기본이고 데이터 매퍼는 객체가 아닌 SQL 구문 자체가 캐시에 저장이 되는 것과 같은 차이점을 낳게 된다. 그렇다고 아이바티스를 ORM의 범주에 포함시키는 데 큰 무리는 없다.

    ORM이 생겨난 원인을 무엇일까? 가장 기본적인 것은 현재의 데이터베이스 프로그래밍에서 일반 JDBC 형태의 개발 방법이 개발자에게 필요 이상의 많은 타이핑과 자원관리를 요구한다는 것이다.

    ORM을 사용해본 개발자는 이 부분에 대해 ORM이 어느 정도 효과를 보인다고 생각할 것이다. 물론 새로운 프레임워크에 대한 학습과 해당 프레임워크가 요구하는 설정작업, 그리고 개발방식은 분명히 개발자에게 또 다른 부담으로 작용하는 것 또한 사실이다. 하지만 개인적으로 개발자는 항상 새로운 어떤 것을 배우고 습득해야 한다.

    그런 면에서 이런 프레임워크로 인한 부담을 느끼지 말고 자기개발의 수단으로 생각했으면 좋겠다. 필자가 처음으로 아이바티스를 접했던 3년 전과는 달리 현재는 국내에 서적도 나와 있고 많은 관련문서가 있어서 개발자들이 아이바티스를 학습하는데 전혀 무리가 없을 듯하다.

    그래서 이번에는 특정 부분에 집중하지 않고 아이바티스를 활용할 수 있는 부분들을 전체적으로 살펴보고 아이바티스 홈페이지를 통해 논의 되고 있는 아이바티스 3.0이 나아가고자 하는 방향을 여기서 간단히 살펴보고자 한다.

      기능에 따른 사용형태

    아이바티스를 사용하는 개발에서는 크게 설정 정보를 가지는 SQLMaps 파일과 SQL구문을 가지는 SQLMap 파일, 그리고 아이바티스 API를 사용하는 자바 코드로 구성이 된다고 볼 수 있다. 먼저 설정정보를 가지는 SQLMaps 파일을 살펴보자. SQLMaps 파일 설정은 이미 많이 알려져 있기 때문에 첨부된 예제소스를 참조하도록 한다.

    샘플용 소스이기 때문에 typeAlias와 SQLMap 파일의 개수가 적다. 하지만 실제 프로젝트에 아이바티스를 적용할 때는 사전에 typeAlias에 대한 명명 규칙을 정해서 중복 되지 않도록 하거나 각각의 SQLMap 파일에 정의해서 StatementNamespaces로 각각을 구분해주어야 설정 파일의 증가로 복잡해질 때 혼동의 여지가 줄어들 것이다.

    전역 세팅에 해당되는 설정과 typeAlias, 그리고 트랜잭션 관리자 및 SQLMap 파일에 대한 위치 정보를 가지고 있다. 전역 세팅에 해당되는 설정은 이외에도 더 있으며 상세한 설명은 이 글의 범위를 벗어나기에 생략한다. 각각의 설정 값에 대한 상세한 정보는 kldp.net에서 호스팅 중인 아이바티스 개발자 가이드 한글문서나 공식 영문문서를 보면 알 수 있다.

    typeAlias는 말 그대로 타입에 대한 별칭이다. 자바의 패키지 구조로 인해 이름이 긴 클래스를 사용할 경우 차후에 불필요한 중복 타이핑을 해야 하는 등 불편이 따른다. 때문에 여기서는 별칭 형태로 정의할 것이다.

    트랜잭션 관리자 부분은 간단히 볼 때 데이터베이스 세팅이다. 간혹 커뮤니티에 아이바티스에서 데이터소스를 두 개 이상 설정할 수 없냐는 질문이 올라오는데 1.x 버전에서는 가능했으나 2.x 부터는 혼란의 소지가 있어 불가능하다. 꼭 필요한 경우라면 이 설정 파일을 데이터 소스 개수만큼 생성하여 동적으로 읽어 들이는 수밖에 없을 듯하다.

    마지막으로 SQL 구문을 가지게 되는 SQLMap 파일이다. 여기서는 클래스 패스 기준으로 설정되었다. 아이바티스 사용자들의 공통적인 고민은 WAS의 재시작 없이 SQL구문이 갱신되는 기능일 것이다. 이 경우 아이바티스 단독으로만 사용할 때는 SQLMap 파일을 파일 경로로 지정해주는 방법을 사용할 수 있겠지만, 이 방법 또한 정상적으로 갱신이 안 되는 경우가 있다고 하니 필자로서는 스프링 프레임워크를 사용하는 방법을 권하고 싶다.

    스프링 프레임워크를 사용하면 WAS를 재시작하지 않고도 SQL구문이 갱신되는 것을 AppFuse를 통해 간단히 체크해볼 수 있다.

    <그림 1>은 이제부터 살펴볼 기본적인 CRUD 작업에 사용된 테이블의 구조다. 계정(account) 정보와 그 계정의 가족 정보(account_family)를 가지는 지극히 간단한 구조로 되어 있다. 하지만 여기서 살펴볼 아이바티스의 기능을 구현하기에는 더없이 적절한 구조라고 생각된다.

    <그림 1> ER 다이어그램


    일반적인 CRUD 작업
    데이터 매퍼인 아이바티스는 SQL ‘구문’을 자바 객체로 매핑하기 때문에 기본적으로 정적인 CRUD 작업에 가장 최적화되어 있다고 할 수 있다. 물론 데이터베이스 함수 및 프로시저, 동적 SQL 처리에도 사용할 수는 있지만 약간의 제약이 있게 마련이다. 여기서는 SQL 구문의 재사용을 위해 요소를 사용했고 이를 요소를 사용해서 다른 구문에서 가져다가 사용하고 있다.

    쿼리문을 일종의 특정 id값을 가지는 xml에 저장하고 그 id를 기준으로 호출해서 사용하는 게 아이바티스의 기본 사용법이다. 이 파일을 이해하는데 별무리가 없으리라 생각된다. 그러면 이 SQL 구문들을 어떻게 호출해서 사용하면 좋을까? 자바 코드를 보자.

     <리스트 1> CRUD 작업을 위한 SQLMap 파일


    <sql id="selectAccount_frag">
    select
    acc_id,
    acc_first_name,
    acc_last_name,
    acc_email
    from account
    </sql>

    <select id="selectAccountById" parameterClass="int" resultClass=vAccount">
    <include refid="selectAccount_frag"/>
    where acc_id = #id#
    </select>

    <insert id="insertAccount" parameterClass="Account">
    insert into account (
    acc_id,
    acc_first_name,
    acc_last_name,
    acc_email
    ) values (
    #id#, #firstName#, #lastName#, #emailAddress#
    )
    </insert>



    자바 코드에서는 각각의 SQL 구문을 호출하는 형태를 <리스트 2>와 같이 취하고 있다. 사전에 아이바티스 설정 파일을 통해 관련 정보를 얻는 부분이 static 구문 안에 처리가 되어 있다. 이 소스는 아이바티스를 처리하는 결과를 보기 위해 log4j 설정과 아이바티스 설정 정보를 읽어오는 두 가지로 구성이 되어 있다.

    log4j.xml 파일과 아이바티스 설정 파일의 위치를 클래스 패스 기준으로 가져오도록 했다. SqlMapClient가 제공하는 각각의 메소드에 SQLMap 파일에 정의된 SQL 구문의 id와 인자로 넣어줄 객체를 정의하는 형태를 취한다. 짐작하겠지만 SQL 구문의 id와 일치하는 SQL 구문에 해당 객체의 값이 인자로 전달되어서 내부적으로 java.sql의 PreparedStatement 객체 생성 후 일반 JDBC처럼 처리된다.

     <리스트 2> CRUD 작업을 위한 자바 코드


    private static SqlMapClient sqlMapper;

    static {
    try {
    // iBATIS SQLMaps setting
    Reader reader = Resources.getResourceAsReader("kr/or/openframework/dao/ibatis/SqlMapConfig.xml");
    sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
    reader.close()
    } catch (IOException e) {
    throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
    }
    }

    public static Account selectAccountById(int id) throws SQLException {
    return (Account) sqlMapper.queryForObject("selectAccountById", id);
    }
    public static String insertAccount(Account account) throws SQLException {
    sqlMapper.insert("insertAccount", account);
    return "SUCCESS";
    }



    프로시저
    예제를 위해 필자는 다음처럼 간단한 프로시저를 생성했다. 여기서는 IN 타입의 파라미터만을 사용했지만 IN과 OUT, INOUT 타입 모두 지원한다. 여기서 사용된 프로시저는 인자로 들어온 값을 id로 해서 샘플용 데이터를 생성한다.

     <리스트 3> 프로시저 생성 구문


    drop procedure if exists procedurein;

    delimiter // ;

    create procedure procedurein (in p_param int)
    begin
    insert into account (
    acc_id,
    acc_first_name,
    acc_last_name,
    acc_email
    ) values (
    p_param, "procedure_test", "procedure_test", "test@test.com"
    );
    end;
    //

    delimiter ; //



    프로시저 호출은 일반적으로 콘솔 창에서 실행하는 것처럼 하고 { }로 감싸주면 된다. 처리 자체는 오히려 CRUD보다 간단하다고 할 수 있으나 직접 해보면 쉽지 않다는 것을 알 수 있다.

     <리스트 4> 프로시저 호출을 위한 SQLMap 파일


    <procedure id="inProcedure" parameterClass= "java.lang.Integer">
    { call procedurein(#val#) }
    </procedure>



     <리스트 5> 프로시저 호출을 위한 자바 코드


    public static String callInTypeProcedure(int id) throws SQLException {
    sqlMapper.update("inProcedure", new Integer(id));
    return "SUCCESS";
    }



    프로시저의 처리는 아이바티스 홈페이지나 메일링 리스트를 통해 끊임없이 제기되는 문제 중에 하나이다. 개발자와 데이터베이스마다 구현 방식이 조금씩 다른 탓도 있겠지만 여러 가지 눈에 띄는 어려움이 존재하기 때문에 아이바티스 문서를 보면 꼭 표준 형태의 프로시저를 사용하도록 권장하고 있다.

    필자의 경우에도 오라클(Oracle)에서는 정상적으로 프로시저 형태의 샘플 코드를 테스트 했으나 MySQL로 작성하면서 이런저런 문제에 봉착했었다. 실제 프로젝트에서 아이바티스를 사용하여 프로시저를 처리할 때는 프로시저 사용 패턴을 정의하고 사전에 정상적으로 처리가 되는지 테스트 해보길 권하고 싶다.

    <표 1> 프로시저 처리시 사용할 메소드에 대한 권고사항


    앞의 예제는 IN 파리미터에 값을 전달하고 내부적으로 처리한 후에 어떠한 데이터도 반환하지 않기 때문에 update() 메소드가 사용되었다(프로시저 처리 시 결과 세트를 반환하고 데이터를 업데이트 할 경우, 요소의 commitRe quired 속성 값을 true로 세팅해줘야 한다).

    N+1 문제

     <리스트 6> N+1문제를 가지는 형태의 SQLMap 파일


    <resultMap id="get_account_family_nplus1" class="Account">
    <result property="id" column="id" />
    <result property="firstName" column="firstName" />
    <result property="lastName" column="lastName" />
    <result property="emailAddress" column= "emailAddress" />
    </resultMap>

    <resultMap id="get_family_nplus1" class="Family">
    <result property="acc_id" column="id" />
    <result property="fullName" column="fullName" />
    <result property="account" column="id" select= "getFamiliesUsingNplus1" />
    </resultMap>

    <sql id="selectAccount_frag">
    select
    acc_id as id,
    acc_first_name as firstName,
    acc_last_name as lastName,
    acc_email as emailAddress
    from account
    </sql>

    <select id="selectAccountWithFamilyUsingNplus1" parameterClass="int" resultMap="get_family_nplus1">
    select
    acc_id as id,
    family_fullname as fullName
    from Account_family
    where acc_id = #id#
    </select>

    <select id="getFamiliesUsingNplus1" parameterClass="int" resultMap="get_account_family_nplus1">
    <include refid="selectAccount_frag"/>
    where acc_id = #id#
    </select>



    log4j를 이용해 실제로 수행되는 SQL문을 찍어보면 다음과 같이 표시된다.

    Executing Statement: select acc_id as id, family_fullname as fullName from Account_family where acc_id = ?
    Executing Statement: select acc_id, acc_first_name, acc_last_name, acc_email from account where acc_id = ?
    Executing Statement: select acc_id, acc_first_name, acc_last_name, acc_email from account where acc_id = ?

    2(N)개의 데이터를 가져오기 위해 실제로는 SQL 문을 한 번 더(+1) 수행하여 총 3번(Account_family에 한번, Account에 두 번)을 실행하게 되는 셈이다. 이것을 N+1 문제라고 하는데 이를 개선하기 위해 groupBy를 사용할 수 있다.

     <리스트 7> N+1문제를 가지는 형태의 자바 코드


    @SuppressWarnings("unchecked")
    public static List<Account> selectAccountWithFamilyUsingNPlus1(int id) throws SQLException {
    List<Account> familys = (ArrayList)sqlMapper.queryForList("selectAccountWithFamilyUsingNplus1", new Integer(id));
    return familys;
    }



     <리스트 8> N+1문제를 가지지 않는 형태의 SQLMap 파일


    <resultMap id="get_account_family_avoidnplus1" class= "Account" groupBy="id">
    <result property="id" column="id" />
    <result property="firstName" column="firstName" />
    <result property="lastName" column="lastName" />
    <result property="emailAddress" column= "emailAddress" />
    <result property="families" resultMap= "Account.get_family_avoidnplus1"/>
    </resultMap>

    <resultMap id="get_family_avoidnplus1" class="Family">
    <result property="acc_id" column="id" />
    <result property="fullName" column="fullName" />
    </resultMap>

    <select id="selectAccountWithFamilyAvoidNplus1" parameterClass="int" resultMap= "get_account_family_avoidnplus1">
    select
    a.acc_id as id,
    a.acc_first_name as firstName,
    a.acc_last_name as lastName,
    a.acc_email as emailAddress,
    f.family_fullname fullName
    from account a left join account_family f
    on a.acc_id=f.acc_id
    where a.acc_id=#id#
    </select>



     <리스트 9> N+1문제를 가지지 않는 형태의 자바 코드


    @SuppressWarnings("unchecked")
    public static List<Account> selectAccountWithFamilyAvoidNPlus1(int id) throws SQLException {
    List<Account> familys = (ArrayList<Account>)sqlMapper.queryForList("selectAccountWithFamilyAvoidNplus1", new Integer(id));
    return familys;
    }




    조인 구문과 groupBy를 사용하면 다음처럼 일반 join 문을 사용하여 처리를 하기 때문에 N+1과 같은 문제가 발생하지 않는다. 현재는 이 방법이 가장 추천된다고 할 수 있다. 하지만 방법적으로 하위 결과 맵을 사용하는 것이 추천되는 방법이라고 보기는 어려울 듯하다. 아이바티스 3.0에서는 좀 더 개선된 방법이 제공될 것으로 짐작된다.

    Executing Statement: select a.acc_id, a.acc_first_name, a.acc_last_name, a.acc_email, f.family_fullname from account a left join account_family f on a.acc_id=f.acc_id where a.acc_id=?

    동적 SQL

     <리스트 10> 동적 SQL을 사용하는 SQLMap파일 내용


    <select id="selectAccountDynamic" parameterClass="Account" resultClass="Account">
    <include refid="selectAccount_frag" />
    <dynamic prepend="WHERE">
    <isGreaterEqual prepend="AND" property= "id" compareValue="2">
    acc_id = 1
    </isGreaterEqual>
    </dynamic>
    </select>



     <리스트 11> 동적 SQL을 호출하는 자바코드


    @SuppressWarnings("unchecked")
    public static List<Account> selectAccountDynamic(Account account) throws SQLException {
    List<Account> accounts = (List<Account>)sqlMapper.queryForList("selectAccountDynamic", account);
    return accounts;
    }



    필자의 경우 인자로 넣어준 id의 값이 3이었기 때문에 다음처럼 WHERE acc_id =1이 추가되어 처리되었다. 동적 SQL의 경우 자바 코드가 아닌 XML의 태그로 동적 SQL을 생성하기 때문에 손에 익지 않아 불편할 수도 있다. 이미 아이바티스 개발팀은 이 동적 SQL 부분에 대한 개선작업을 진행하고 있다. 그 결과물로 3.0에서 도입될 방식에 대해 잠시 뒤에 살펴보도록 하겠다.

     <리스트 12> 동적 SQL을 호출하는 결과


    Executing Statement: select acc_id as id, acc_first_name as firstName, acc_last_name as lastName, acc_email as emailAddress from account WHERE acc_id = 1



      아이바티스 3.0 소식

    아이바티스 3.0 개발은 다음과 같은 방향으로 진행이 된다.

    - 테스트 주도 개발
    - 성능보다는 코드의 간결성
    - 복잡한 디자인 보다는 간결한 디자인
    - 하나의 JAR파일
    - 다른 라이브러리의 의존성을 없앰
    - 더 나은 플러그인 지원
    - 추가적인 플러그인을 위한 프로젝트(http://sourceforge.net/ projects/ibatiscontrib/)

    역시나 기본적으로 계속 간결한 프레임워크를 유지하면서 많은 사용자들이 원하는 기능은 플러그인 형태로 제공하는 것이 기본적인 개발 방향임을 짐작할 수 있다. 역시 아이바티스는 간단함 내지 간결함으로 표현할 수 있는 프레임워크이다.
    그럼 저 기본 방향을 염두에 두고 현재 다소 형상화되어 보이는 3.0 기능에 대해 간단히 살펴보자.

    인터페이스 바인딩
    일단 다음과 같은 기존 코딩 방식에 대해 살펴보자. 기존 방식의 문제점은 매핑 구문명이 문자열 기반이라 매핑 구문명의 철자가 잘못되어 있을 경우 에러가 발생하게 되고 컴파일시가 아닌 런타임 시 에러가 발견할 수 있게 된다. 더군다나 문자열 기반이라 SQLMap 파일의 증가는 곧 사용할 구문에 대한 체크에 일부 시간을 소요할 수밖에 없도록 만드는 계기가 된다.

    그리고 반환 타입은 형 변환을 통해 명시화되지만 실제로 반환 타입의 모호로 인해 형 변환 시 ClassCastException은 아이바티스 사용자라면 한번쯤 겪게 되는 에러가 된다. 즉 애매한 형 변환과 문자열 기반의 매핑 구문은 결과적으로 대부분의 에러가 런타임 시 발생하여 개발을 힘들게 만드는 요인이 되고 있다.

    이런 점을 해결하기 위해 나온 것인 이 인터페이스 바인딩이다.

    기존에 XML에 타입을 선언하고 문자열 기반으로 구문을 호출하는 것 대신에 좀 더 서술적이고 타입에 안전한 인터페이스의 사용으로 앞서 언급된 문제점을 많이 보완해 나가고 있다. 다음의 코드는 기존 방식의 호출을 새로운 인터페이스 바인딩 방법으로 호출한 것이다.

    애매한 형 변환 작업이 없고 문자열 기반의 매핑 구문을 사용하지 않아 기본적으로 컴파일 시 많은 에러를 찾아낼 수 있다. 요즘처럼 IDE를 기본적으로 사용하는 환경이라면 얼마나 많은 도움이 될지는 의심할 여지가 없다.

    결과적으로 인터페이스 바인딩을 통해 매핑 구문명과 파라미터 타입, 결과 타입을 자동적으로 알 수 있게 되는 셈이다.

    다중 레벨 설정
    아이바티스의 오랜 설정 방식인 XML은 3.0에서도 역시 좋은 방법이 되겠지만 3.0에서 디폴트 설정 방법이 되지는 않는다. 3.0에서는 다음과 같은 다중 레벨 설정이 가능하게 된다.

    - 관례(Convention)
    - 어노테이션(말 그대로 하면 주석) : 앞의 관례보다 우선시 된다.
    - XML : 앞의 관계, 어노테이션보다 우선시 된다.
    - 자바 API : 앞의 관례, 어노테이션, XML보다 우선시 된다.
    관례는 메소드 시그니처로 정해진 규칙이라고 보면 된다.

    Employee getEmployee (int id); 라는 메소드 시그니처는 다음과 같은 SQL과 동일 시 된다고 볼 수 있다.

    SELECT id, firstName, lastName FROM Employee WHERE id = ?

    여기서 메소드 반환 타입의 이름이 테이블 명이 되고 메소드의 인자로 주어진 값이 자동으로 WHERE 조건문을 구성한다고 볼 수 있다. 간단한 조건문이나 들어가는 형식의 전체 데이터를 뽑는 기능이라면 이 메소드를 선언하여 추가 작업 없이 해당 기능이 구현할 수 있다.

    어노테이션으로 설정하기
    XML 설정을 넘어서 어노테이션으로 메타데이터 정보를 설정하는 기능이 많이 도입되었다. 이에 아이바티스도 이러한 기능을 추가적으로 지원한다. 현재 아이바티스의 XML 파일은 다음과 같은 정보를 가진다.

    - 설정
    - 메타 정보
    - 코드

    설정은 환경적인 정보이다.

    메타정보는 결과 맵과 파라미터 맵, 그리고 캐시 모델들을 나타내고 코드는 SQL과 동적 SQL 요소를 포함한다. 설정 정보는 properties 파일이나 XML에 담겨야하고, 코드는 자바 코드나 XML에 담겨야 한다. 단 메타정보만이 어노테이션에서 처리가 가능하도록 될 것이다.

    어노테이션의 예제는 다음과 같다. 앞의 관례에 의한 방식에서 칼럼 별 타입을 정의하고 조건문을 구체화하기 위해 어노테이션이 사용된 것을 볼 수 있다.

     <리스트 13> CRUD 작업을 위한 어노테이션 사용 예제


    @Select({"SELECT #id(EMP_ID:NUMERIC), #firstName(FIRST_NAME:VARCHAR), #lastName(LAST_NAME:VARCHAR) ",
    "FROM EMPLOYEE",
    "WHERE EMP_ID = @id"})
    Employee selectEmployee(int id);

    @Insert({"INSERT INTO EMPLOYEE (EMP_ID, FIRST_NAME, LAST_NAME)",
    "VALUES (@id, @firstName, @lastName)"})
    void insertEmployee(Employee emp);

    @Delete("DELETE EMPLOYEE WHERE EMP_ID = @id")
    void deleteEmployee(int id);



    <리스트 14>와 같은 형식의 어노테이션도 사용 가능하게 된다. 여기서는 ResultClass와 PropertyResult를 추가적으로 어노테이션을 통해 정의한 것이다.

     <리스트 14> ResultClass, PropertyResults를 사용하는 어노테이션 예제


    @ResultClass (Department.class)
    @PropertyResults({
    @Result(property="id", column="DEPT_ID"),
    @Result(property="name", column="NAME"),
    @Result(property="employees",
    nestedQuery=@QueryMethod(type=CompanyMapper.class, methodName="getEmployeesForDeparment", parameters="id"))
    })
    @Select("SELECT #id, #name FROM DEPARTMENT WHERE COMP_ID = @id ")
    List<Department> getDepartmentsForCompany(int id);



    <리스트 15>와 같이 캐싱을 설정할 수도 있다.

     <리스트 15> 캐싱 설정의 어노테이션 사용 예제


    @CacheContext("Employee")
    public class EmployeeMapper {
    void insertEmployee(Employee emp);
    Employee getEmployee(int id);
    List<Employee> findEmployeesLike(Employee emp);
    }



    기존 설정이라면 다음과 같은 의미를 가진다.

     <리스트 16> 캐싱 설정의 기존방식 예제


    <Mapper cacheContext="Employee">
    <Insert id="insertEmployee" ...> ... </Insert>
    <Select id="getEmployee" ...> ... </Select>
    <Select id="findEmployeesLike" ...> ... </Select>
    </Mapper>



    @flushCache
    List<Employee> updateAndGetSpecialEmployees();
    는 다음과 같은 의미를 가진다.

    <Select id=“findEmployeesLike” flushCache==“true”...> ... </Select>

    예제를 통해 보면 현재의 설정을 일일이 XML 파일에 적어야 할 사항을 어노테이션을 통해 설정을 함으로써 일단 XML 파일 내용의 갱신 문제에 좀 더 자유로워 질 수 있을 듯하다. 한편, 개발자가 초기 XML 설정 외에 대부분의 작업을 자바 소스에서 제어함으로써 작업도 한결 수월하게 할 수 있을 것이다.

    XML 설정 향상
    다음은 XML 설정 향상과 관련된 주요 내용들이다.

    1. 필드와 생성자 파라미터 그리고 자바빈즈 프로퍼티에 결과 및 파라미터를 맵핑된다.
    2. N+1 문제를 해결하는 조인 매핑과 groupBy는 사용이 더 쉬워진다. <리스트 17>의 요소를 사용해서 하위 결과 맵을 생성하는 작업이 필요 없도록 한다.
    3. 결과 맵과 파라미터 맵은 기본적으로 ‘자동 매핑’ 되고 이름이 일치하지 않는 프로퍼티만을 명시한다.
    4. 기능적으로 좀 더 뛰어나면서 간단한 타입 핸들러 구현체와 데이터 타입 변환 필터를 제공할 것이다.
    5. 가장 큰 변화는 XML 파일이 Mapper.class의 복사본과 함께 처리한다는 점이다. 이를테면 EmployeeMapper.xml은 클래스패스에 존재하는 EmployeeMapper.class를 위해 로드 된다. 해당 매퍼 클래스의 객체를 생성하면 자동으로 같은 이름의 매퍼 XML 파일이 로드 되는 형식이라고 짐작된다. 객체 생성에 따라 매퍼 XML 파일이 로드 되는 형식이라면 SQL 구문의 갱신이 3.0에서는 어느 정도 해결될 듯하다.

     <리스트 17> Mapper용 XML설정


    <Mapper>
    <ResultMap id="selectACompanyWithJoin" resultClass= "Company">
    <Constructor column="C.COMP_ID"/>
    <Constructor column="C.NAME"/>

    <Property name="departments.id" column="D.DEPT_ID"/>
    <Property name="departments.name" column="D.NAME"/>

    <Collection type="Department.class" property= "departments" groupBy="id"/>
    <Collection type="Employee.class" property= "departments.employees" groupBy="departments.id"/>
    </ResultMap>

    <Select id="selectACompanyWithJoin" parameters= "id:int,order:string">
    SELECT
    #{id},
    #{name},
    #{departments.id},
    #{departments.name},
    FROM COMPANY C
    INNER JOIN DEPARTMENT D ON C.COMP_ID = D.COMP_ID
    INNER JOIN EMPLOYEE E ON D.DEPT_ID = E.DEPT_ID
    WHERE
    C.COMP_ID = @{id}
    ORDER BY ${order}
    </Select>
    </Mapper>



    동적 SQL
    현재의 요소를 사용하는 방법 외에도 3.0에서는 다음과 같은 방법이 가능하게 된다. 아무래도 자바 개발자에게는 XML 에서 문자열을 조작하는 것보다는 자바 로직으로 처리하는 편이 훨씬 수월할 것이다.

     <리스트 18> SQLSource를 확장한 동적 SQL시용 예제


    public class GetAccountListSQL extends SQLSource {
    public String getSQL(Object param) {
    Account acct = (Account) param;
    append("select * from ACCOUNT");
    prepend(“WHERE”); // 다음의 append 앞에 기본적으로 추가한다.
    if (exists(acct.getEmailAddress())) {
    append("AND", "ACC_EMAIL like #EmailAddress#"); // 필요하다면 첫 번째 인자를 붙이겠지만 그렇지 않다면 첫 번째 인자는 무시된다.
    }
    if (greaterThan(0,acct.getID())) {
    append("AND", "ACC_ID = #ID#");
    }
    prepend(); // 앞의 prepend 뒤에 아무 코드가 없다면 앞의 prepend를 지운다.
    append ("order by ACCT_LAST_NAME");
    }
    }



    <리스트 18>은 다음과 같이 사용할 수 있다.

    @SQLSource(GetAccountListSQL.class)
    List<Accout> getAccountList(Account acct);

    또는 다음처럼도 가능하다.

    <Select id=“getAccountList” source=“org.apache.GetAccount ListSQL” ...> ...
    </Select>

    그 외에 테이블 관계를 나타내기 위한 간단한 기능이 추가되고 SQL 생성을 지원하는 몇 가지 옵션도 추가될 것으로 보인다.

    지금까지 개인적으로 원했던 기능 중에 3.0에서 추가되도록 활발히 진행 중인 것 위주로 살펴보았다. 하지만 곰곰이 생각해보면 아이바티스가 추구했던 간결함은 오히려 반감되고 있는 게 아닌가 하는 우려도 든다. 아이바티스의 장점은 간결함이다. JDBC에 익숙한 개발자라면 몇 시간의 교육만으로도 실제 프로젝트에 적용할 수 있을 정도다.

    단점이라면 매핑 작업이 번거롭다는 점을 들 수 있을 것이다. 파라미터 맵과 결과 맵에 매핑해주는 작업이 JDBC를 그대로 사용하는 것보다 그렇게 쉬운 작업이 아니다. 그럼에도 불구하고 아이바티스를 많이 사용하게 되는 데에는 충분히 사용할만한 장점이 있기 때문일 것이다. 앞으로도 발전하는 아이바티스의 모습을 기대해 본다. @

    참고자료
    1. 아이바티스 홈페이지
    2. AppFuse 홈페이지
    3. 아이바티스 공식 문서 한글화 프로젝트
    4. ORM의 또 다른 핵 iBATIS SQLMaps
    5. 아이바티스에서 프로시저사용하기
    6. http://www.mail-archive.com/user-java@ibatis.apache.org/msg02045.html
    7. 아이바티스 3.0 화이트보드


    * 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.
    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:23
    반응형

    실무에서 SQL문을 작성하다 보면 동적인 쿼리문 작성을 작성해야 할 때가 많이 있다.
    이때 지겹게 if~else if 문을 통해 아주 지저분한 소스 코드를 생성할 때가 왕왕 있게 마련이다.
    이때 ibatis에서는 아주 깔금하게 구현할 수 있는 방법을 제공해 준다.

    <statement id="dynamicGetAccountList" resultMap="account-result">
      select * from account
      <dynamic prepend="WHERE">
        <isNotNull prepend="AND" property="firstName">
          (acc_first_name = #firstName#
        <isNotNull prepend="OR" property="lastName">
           acc_last_name = #lastName#
        </isNotNull>
        )
        </isNotNull>
        <isNotNull prepend="AND" property="emailAddress">
          acc_email like #emailAddress#
        </isNotNull>
        <isGreaterThan prepend="AND" property="id" campareValue="0">
          acc_id = #id#
        </isGreaterThan>
      </dynamic>
      order by acc_last_name
    </statement>

    상황에 의존적인 위 동적 statement로 부터 각각 다른 16가지의 SQL문이 생성될 수 있다. if-else구조와 문자열 연결을 코딩하는 경우 수백라인이 필요할 수도 있다.
    동적 statement를 사용하는 것은 몇몇 조건적인 태그를 추가하는 것처럼 간단하게 작성할 수 있다.

    이러한 조건들에 대해 간단히 정리하면 아래와 같다.

    바이너리 조건 요소-바이너리 조건 요소는 정적값 또는 다른 프로퍼티값을 위한 프로퍼티값과 비교한다. 만약 결과가 true라면 몸체부분의 SQL쿼리가 포함된다.

    바이너리 조건 속성

    prepend

    Statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

    property

    비교되는 property(필수)

    compareProperty

    비교되는 다른 property (필수 또는 compareValue)

    compareValue

    비교되는 값(필수 또는 compareProperty)


    <isEqual>

    프로퍼티가 값 또는 다른 프로퍼티가 같은지 체크

    <isNotEqual>

    프로퍼티가 값 또는 다른 프로퍼티가 같지 않은지 체크

    <isGreaterThan>

    프로퍼티가 값 또는 다른 프로퍼티 보다 큰지 체크

    <isGreaterEqual>

    프로퍼티가 값 또는 다른 프로퍼티 보다 크거나 같은지 체크

    <isLessThan>

    프로퍼티가 값 또는 다른 프로퍼티 보다 작은지 체크

    <isLessEqual>

    프로퍼티가 값 또는 다른 프로퍼티 보다 작거나 같은지 체크


    사용법 예제)

    <isLessEqual prepend="AND" property="age" compareValue="18">

      ADOLESCENT = 'TRUE'

    </isLessEqual>

    단일 조건 요소-단일 조건 요소는 특수한 조건을 위해 프로퍼티의 상태를 체크한다.

    prepend

    statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

    property

    체크하기 위한 프로퍼티(필수)

    <isPropertyAvailable>

    프로퍼티가 유효한지 체크

    (이를 테면 파라미터의 프로퍼티이다.)

    <isNotPropertyAvailable>

    프로퍼티가 유효하지 않은지 체크

    (이를 테면 파라미터의 프로퍼티가 아니다.)

    <isNull>

    프로퍼티가 null인지 체크

    <isNotNull>

    프로퍼티가 null이 아닌지 체크

    <isEmpty>

    Collection, 문자열 또는 String.valueOf() 프로퍼티가 null이거나 empty(“” or size() < 1)인지 체크

    <isNotEmpty>

    Collection, 문자열 또는 String.valueOf() 프로퍼티가 null 이아니거나 empty(“” or size() < 1)가 아닌지 체크


    사용법 예제)

    <isNotEmpty prepend="AND" property="firstName">

      FIRST_NAME = #firstName#

    </isNotEmpty>

    다른 요소들
    Parameter Present : 파라미터 객체가 존재하는지 체크
    Parameter Present Attributes : prepend - the statement에 붙을 오버라이딩 가능한 SQL부분

    <isParameterPresent>

    파라미터 객체가 존재(not null)하는지 체크

    <isNotParameterPresent>

    파라미터 객체가 존재하지(null) 않는지 체크

     

    사용법 예제)

    <isNotParameterPresent prepend="AND">

    EMPLOYEE_TYPE = 'DEFAULT'

    </isNotParameterPresent>

    Iterate : 이 태그는 Collection을 반복하거나 리스트내 각각을 위해 몸체 부분을 반복한다.
    Iterate Attributes :
      prepend - the statement에 붙을 오버라이딩 가능한 SQL부분 (옵션)
      property - 반복되기 위한 java.util.List타입의 프로퍼티 (필수)
      open - 반복의 전체를 열기 위한 문자열, 괄호를 위해 유용하다. (옵션)
      close - 반복의 전체를 닫기 위한 문자열, 괄호를 위해 유용하다. (옵션)
      conjunction - 각각의 반복 사이에 적용되기 위한 문자열, AND 그리고 OR을 위해 유용하다. (옵션)

    <iterate>

    java.util.List 타입의 프로퍼티 반복


    사용법 예제)

    <iterate prepend="AND" property="userNameList" open="(" close=")" conjunction="OR">

    username = #userNameList[]#

    </iterate>


    주의:iterator요소를 사용할 때 리스트 프로퍼티의 끝에 중괄호[]를 포함하는 것은 중요하다. 중괄호는 문자열처럼 리스트를 간단하게 출력함으로부터 파서를 유지하기 위해 리스트처럼 객체를 구별한다.

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:21
    반응형

    1. iBatis란?

    iBatis는 데이터베이스에 있는 자원들을 보다 편리하게 가져오기 위한 기술이다. 하지만 DB에 있는 테이블과 자바 객체간의 직접적인 동기화를 이루는 ORM(Object Relational Mapper)는 아니며, 자바빈즈를 PreparedStatement의 바인드 변수인 파라미터(?)와 ResultSet으로 맵핑시켜주는 기능으로 지금에 와서는 SQL Maps 또한 ORM이라고도 한다.

    즉, iBatis는 sql문이 자동 생성되는 것이 아니며, 특정 XML문서에 임베디드된 sql문을 개발자가 직접 정의 하여 자바 코드와 sql문을 XML문서로 분리를 시켜 놓는다. 그리고 자바 객체를 sql문의 XML문서에서 맴핑을 걸어 놓아 보다 쉽게 Value Object를 얻기위해 사용되는 SQL Mapper이다.


    2. 환경설정

     2-1) 우선 다음 사이트에 접속하여 오른쪽 항목에서 [iBaits]를 선택하여 iBatis의 라이블러리를 내려 받으러 접근한다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-2) 다음에 확인되는 화면의 왼쪽 메뉴 중..[Get software...]에 있는 [for Java]를 선택한다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-3) 다음 그림과 같이 [Download iBATIS Java 2.X.X]를 선택한다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-4) 다운로드 대화창에서 [저장]을 선택하여 기억하기 쉽고 원하는 장소에 내려받아 압축을 풀어둔다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-5) 압축을 풀었다면 다음 그림과 같은 폴더가 생겼을 것이다. 여기까지 확인이 되었다면 우리의 넷빈을 실행 시켜 보자!

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-6) 다음과 같은 넷빈 초기화면에서 앞서 준비했던 Oracle 라이블러리와 iBatis 라이블러리를 사용할 수 있도록 [Libraties]에 등록해 보자!

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-7) 다음과 같은 Library Manager창에서 아래쪽에 있는 [New Labrary...]버튼을 선택하여 새로운 라이블러리를 등록하기 위해 그림과 같이 입력한다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-8) 그리고 다음과 같이 Oracle라이블러리 파일을 선택하여 추가 한다.

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-9) 여기까지 했다면, 다음 그림과 같이 jar파일이 추가 됐음을 알 수 있다.

    이미지를 클릭하면 원본을 보실 수 있습니다.

    물론 이미 Oracle라이블러리가 등록되어 있었다면 지금까지 2-7에서 2-9까지의 작업은 생략해도 된다.


    2-10) 이제 iBatis 라이블러리를 등록하기 위해 [New Labrary...]버튼을 선택한 후, 다음 그림과 같이 입력하고 [OK]버튼을 선택하자!

    이미지를 클릭하면 원본을 보실 수 있습니다.


    2-11) 그리고 [Add Jar/Folder...]버튼을 선택하여 앞서 iBatis 라이블러리 파일을 압축 해제한 곳에 [lib]라는 폴더가 있다. 그곳의 내용이 다음 그림과 같을 것이다. 선택한 후 추가 하자!

    이미지를 클릭하면 원본을 보실 수 있습니다.


    이렇게 해서 iBatis 라이블러리를 등록함과 동시에 준비 작업은 끝이 났다. 첫 강좌를 마무리 하면서 이런 iBatis 라이블러리의 Tutorial문서는 앞 2-3화면에서 살~짝만 내리면 다음 그림과 같이 [Korean]항목이 보기 드물게 [Japanese]보다 우위에 있는 것을 확인 할 수 있다.

    원하는 국적을 선택하여 접근해 보자! Tutorial문서가 pdf파일로 제공됨을 알 수 있다. ^^;

    이미지를 클릭하면 원본을 보실 수 있습니다.

    http://cafe.daum.net/javaclubj
    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:18
    반응형



    iBATIS 에 대한 보다 자세한 소개는 http://ibatis.com 을 참고하세요

    iBATIS  도입 이유

    iBATIS 는 그들의 말로는 Data Mapper 라고 합니다.(iBATIS 개발자 가이드 참고)

    그들이 이야기하듯이 복잡할 수도 있지만 일부러 간단한 사용법을 제공함으로써 사용의 혼란과 난이도를 낮추고자 했습니다.

    아마 제작자들도 ORM 툴과는 그 성격이 다르게 생각하고 있는 모양입니다.

    JAVA 에서 Object 를 사용함에 있어서 getXXX , setXXX 로의 접근은 사용법과 유지보수 측면에서 이미 standard 로 여겨지고 있습니다.

    즉 대부분의 작업자들이 이렇게 작업을 합니다.

    그런데 이러한 객체를 만들어 낼때 ORM(혹은 Data Mapper) 을 사용하기 전 아래와 같은 코드를 가지고 작업을 할것입니다.

     

    MemberData mb=new MemberData();
      
      mb.setId(req.getParameter("ID"));
      mb.setPassword(req.getParameter("PASSWORD"));
      mb.setAddress(req.getParameter("ADDRESS"));
      mb.setAdminMemo(req.getParameter("ADMIN_MEMO"));
      mb.setBirthDay(req.getParameter("BIRTHDAY1")+req.getParameter("BIRTHDAY2")+req.getParameter("BIRTHDAY3"));
      mb.setBirthGubun(req.getParameter("BIRTH_GUBUN"));
      mb.setEngName(req.getParameter("ENG_NAME"));
      mb.setGender(req.getParameter("GENDER"));
      mb.setHandPhone(req.getParameter("HAND_PHONE1")+"-"+req.getParameter("HAND_PHONE2")+"-"+req.getParameter("HAND_PHONE3"));
      mb.setHomepage(req.getParameter("HOMEPAGE"));
      mb.setKrName(req.getParameter("KR_NAME"));
      mb.setMail(req.getParameter("MAIL"));

    mgr.insert(mb);

     

    정말 단순한 노가다의 연속이라는 ;;;

    하지만 iBATIS 를 사용하게 되면 아래와 같이 코드가 심플해 집니다.

     

    mb=(MemberData)sqlMap.queryForObject("getMember",id);

    mgr.insert(mb);

     

    위의 단순한 비교에서 보시다 시피 상당한 코딩의 축소로 인해 개발자로 하여금 지겨운 노가다에서 해방하게 됩니다.

    (익숙해 질경우 20%로 축소 시켜 준다고 합니다.)

    개발자가 필수로 갖춰어야 할 "게을러질 수 있는 권리' 를 찾을 수 있도록 해줍니다.

     

    iBATIS 의 설치

    설치는 한가지 설정으로 끝납니다.

    http://ibatis.com 을 방문해서 iBATIS 최신 버젼을 다운로드 하셔서 lib 디렉토리에 있는 ibatis-XXX 인 세개의 파일을 APP_HOME/WEB-INF/lib 디렉토리에 넣으시고 CLASSPATH 를 설정하시기 바랍니다.

     

    iBATIS 설정 파일의 종류

    설정 파일은 DATABASE 의 환경을 선택하는 xml 파일과 각 Table 에 쿼리를 저장하는 xml 파일의 두가지 종류로 나뉩니다.

    파일명과 위치는 전혀 상관이 없습니다만 WEB-INF/classes 하위에 두어야 찾아가기 쉽겠죠?

    아래의 스크린 샷은 사용중인 xml 파일의 위치입니다.

     

     

    sqlMapConfig.xml 파일이 설정 파일이며 Member.xml 파일은 Member 에 대한 쿼리문을 담고 있습니다.

    db.properties 파일은 Reader 가 읽어갈 Database 접속 정보를 담고 있습니다.

     

    Beans 만들기

    회원 관리를 위해서 간단한 Beans를 만들어 보겠습니다.

    Bean 이름은 MemberBean으로 하고 member 패키지 하위에 만들어 보도록 하겠습니다.

    먼저 이클립스에서 회원이 가질수 있는 정보를 설정하도록 합니다.

    아래 이미지 처럼 설정이 되겠지요?

     

    그 이후에 이클립스에서 간단하게 getter 와 setter 를 설정할 수 있습니다.

     

     

    이렇게 만들면 bean 작성이 끝났습니다.

    이후의 작업들은 다음과 같습니다.
    환경 설정 xml 파일 만들기
    쿼리문 xml 파일 만들기\Connection Mannager 만들기
    각 Mannager Class 에서 사용하기

     

    저작자 표시
          Tag - ibatis
          DB/iBATIS  |  2008/10/06 02:41





    이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용이며 저작권에 관련한 모든 사항은 마이크로소프트웨어에 있습니다.
    이 문구를 삭제하고 배포시 저작권에 위배될수 있습니다.

    저자 정보 : 이동국(mailto:fromm0@gmail.com)

    현재 울산에 있는 아이티스타에서 근무하고 있으며 주로 현대자동차 관련 프로젝트에 참여하고 있다. 네이버 자바프레임워크 카페 스탭으로 할동하고 있고 오픈프레임워크 사이트를 관리하고 있다. 평소 개발 프레임워크와 웹서비스에 관심을 가지고 있으며 요즘은 AndroMDA에 관련해서 공부를 시작했다.

    ORM의 또 다른 핵 iBATIS SQLMaps

    작년을 비롯해서 현재까지 해외 자바 관련 커뮤니티에서 가장 많이 논의가 되고 있는 부분 중 하나는 ORM이다. 그 이유를 생각해보면 자바개발의 많은 부분을 차지하고 있는 분야가 웹프로그래밍이고 그 웹프로그래밍의 거의 대부분을 차지하는 분야가 데이터베이스관련 처리이기 때문일 것이다. 현재 그 ORM을 대표하는 두 가지가 있다. 하나는 hibernate이고 또 하나는 이번에 소개할 iBATIS의 SQLMaps이다. 한때 객체와 관계형 데이터베이스의 관계 맵핑을 설정하면 SQL문을 자동 생성해 주는 hibernate에 비해 SQL문 자동 생성 기능이 없는 SQLMaps는 진정한 의미의 ORM이 아니다 라는 분위기도 있었지만 관계형 데이터베이스와 통신할 수 있는 유일한 매개체인 SQL문과 객체를 맵핑 시켜준다는 의미에서 현재는 SQLMaps또한 ORM이라고 보고 있다. hibernate의 경우 자바 관련 커뮤니티에서 많이 다루어 진 것으로 알고 있다. 우리는 여기서 SQLMaps에 대해서 알아보고자 한다. SQLMaps의 장점은 무엇일까.? iBATIS에서 밝히는 SQLMaps의 최대 장점은 간단함(simple)이다. 이것은 필자를 포함한 SQLMaps를 사용한 대부분의 개발자들이 인정하는 부분이다. 그 간단함이란 기존의 SQL문을 별다른 수정 없이 그대로 사용할 수 있는 상황에서 단순히 객체와 SQL문의 맵핑을 위한 몇몇 설정값만 설정해 주면 간단하게 ORM의 기능을 경험해 볼 수 있다는 것이다. 이러한 장점은 단순한 설명만으로는 잘 느껴지지 않으리라 본다. 잠시 후 예제를 통해서 정말 SQLMaps가 기존의 JDBC프로그램에 비해 얼마나 간단하게 구현이 되는지 보자.

    SQLMaps는

    앞에서 필자가 SQLMaps는 SQL과 객체를 맵핑시켜주는 도구라고 소개했지만 사실 엄밀하게 따지면 자바빈즈를 PreparedStatement 파라미터와 ResultSet으로 맵핑시켜주는 기능을 담당한다. 즉 PreparedStatement의 ? 에 각각의 파라미터 값을 setString()과 같은 메소드를 사용해서 셋팅하는 과정이나 ResultSet에서 getString()과 같은 메소드를 통해서 임의의 VO객체를 생성하는 과정을 자동으로 해준다. 결과적으로 간단한 xml셋팅만으로 일일이 손으로 작성하던 기존 JDBC형식을 버릴 수가 있다. SQLMaps의 구조를 도식화하면 다음과 같다.

    1.jpg

    iBATIS에서는 결과적으로 기존 데이터베이스 프로그램 코드의 20%정도만 사용해도 80%이상의 같은 기능을 수행할 수가 있게 된다고 밝히고 있고 필자 또한 그렇게 생각하고 있다.

    이론적인 설명은 이쯤에서 잠시 접어두고 실제 사용하는 것을 보고 과연 어떻게 다른가를 알아보자. 아래의 소스는 얼마 전 오픈시드 프로젝트(http://openseed.net)의 ORM 연구회에서 진행한 1차 테스트 프로젝트의 소스이다. 일단 SQLMaps를 사용하기 위해서는 최소 두 가지의 설정파일이 필요하다. SQLMaps 설정파일과 SQLMaps 맵핑 파일이다. 추가적으로 프라퍼티값을 외부로 빼내기 위해서 사용되는 properties파일이 필요할 수 도 있다. 먼저 SQLMaps설정 파일인 SqlMapsConfig.xml을 보자.

    SQLMaps 설정파일

    소스 : SqlMapConfig.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" 
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
    <sqlMapConfig>
       <properties resource="SqlMapConfig.properties" />

       <settings cacheModelsEnabled="true" enhancementEnabled="true"
    lazyLoadingEnabled="true" maxRequests="32" 
    maxSessions="10" maxTransactions="5" 
    useStatementNamespaces="false" />

       <typeAlias alias="comment" type="net.openseed.orm.openboard.domain.Comment"/>
       <typeAlias alias="message" type="net.openseed.orm.openboard.domain.Message"/>
       <typeAlias alias="user" type="net.openseed.orm.openboard.domain.User"/>

       <transactionManager type="JDBC">
          <dataSource type="DBCP">
             <property name="JDBC.Driver" value="${driver}" />
             <property name="JDBC.ConnectionURL" value="${url}" />
             <property name="JDBC.Username" value="${username}" />
             <property name="JDBC.Password" value="${password}" />
             <property name="JDBC.DefaultAutoCommit" value="false" />
          </dataSource>
       </transactionManager>

       <sqlMap resource="Comment.xml" />
       <sqlMap resource="Message.xml" />
       <sqlMap resource="User.xml" />
    </sqlMapConfig>

    xml파일 내용을 보면 크게 5가지로 분류되어 있다. 첫 번째인 <properties>는 프라퍼티값을 외부로 빼내서 사용하기 위해 프라퍼티파일을 사용할 때 해당 프라퍼티파일의 경로를 지정해준다. 프라퍼티 파일은 ‘키=값’ 의 형태로 값을 지정하고 SqlMapConfig.xml에서는 ${키} 의 형태로 사용할 수 있다.

    두 번째인 <settings>은 SQLMaps에서 사용되는 다양한 옵션과 최적화를 위한 값들이다. 각각의 값들은 다음의 표를 참조하길 바란다.

    cacheModelsEnabled SqlMapClient 를 위한 모든 캐시모델을 가능 유무.
    Default: true (enabled)
    enhancementEnabled 런타임시 바이트코드 향상을 가능유무.
    Default: false (disabled)
    lazyLoadingEnabled 모든 늦은(lazy)로딩을 가능유무.
    Default: true (enabled)
    maxRequests 동시에 SQL문을 수행할 수 있는 쓰레드의 수. 셋팅값보다 많은 쓰레드는 다른 쓰레드가 수행을 완료할 때까지 블록 된다.
    Default: 512
    maxSessions 주어진 시간동안 활성화될 수 있는 세션의 수.
    Default: 128
    maxTransactions 한꺼번에 SqlMapClient.startTransaction()에 들어갈 수 있는 쓰레드의 최대갯수. 셋팅값보다 많은 쓰레드는 다른 쓰레드가 나올 때까지 블록 된다.
    Default: 32
    useStatementNamespaces 이 셋팅을 가능하게 하면 당신은 sqlmap이름과 statement이름으로 구성된 전체적인 이름(fully qualified name)으로 맵핑된 statement를 참조해야 한다.
    예를 들면: queryForObject("sqlMapName.statementName");
    Default: false (disabled)

    세 번째인 <typeAlias>는 패키지 명을 포함한 클래스가 너무 길 때 각각의 SQLMaps맵핑 파일에서 사용하기 번거로우므로 별칭을 두어서 간단하게 사용할 수 있다. 하지만 미리 정의된 별칭이 있다. 그 값들은 다음과 같다.

    transactionManager에서 사용되는 별칭
    JDBC com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig
    JTA com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig
    EXTERNAL com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
    dataSource에서 사용되는 별칭
    SIMPLE com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
    DBCP com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
    JNDI com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory

    네 번째인 <transactionManager>는 트랜잭션에 관련된 값을 셋팅하고 하위 데이터소스값을 지정하는 <dataSource>를 가진다. transactionManager의 type속성 값은 JDBC, JTA, EXTERNAL 중에 하나를 사용할 수 있는데 그 각각의 값은 다음과 같은 특징을 가진다.

    • JDBC - Connection commit()과 rollback()메소드를 통해 트랜잭션을 제어하기 위한 JDBC를 사용하게 된다.
    • JTA - 이 트랜잭션관리자는 SQL Maps가 다른 데이터베이스나 트랜잭션 자원을 포함하는 더욱 넓은 범위의 트랜잭션을 포함하도록 하는 JTA전역트랜잭션를 사용한다.
    • EXTERNAL - 이것은 개발자가 직접 트랜잭션을 관리할 때 사용하는 것으로 주로 분산 컴포넌트 기반 시스템 환경에서 컨테이너가 트랜잭션을 관리하는 경우에 사용된다.

    dataSource의 type속성 값은 SIMPLE, DBCP, JNDI 중에 하나를 사용할 수 있다. 이 값은 각각 iBATIS SimpleDataSource 커넥션 풀링, Jakarta DBCP, JNDI를 통한 데이터소스을 사용하게 한다.

    다섯 번째인 <sqlMap>은 SQLMaps맵핑 파일의 위치를 지정한다. resource속성 값에 전체패키지경로명을 포함하는 클래스 명을 써주면 된다.

    기본이 되는 SQLMaps의 설정파일은 이렇게 특별히 어려운 설정 없이 간단하게 설정할 수 있다. 그럼 이제부터는 데이터베이스 작업별로 SQLMaps를 어떻게 사용하는지 보여주기 위한 요소인 자바소스와 SQLMaps맵핑 파일을 보도록 하자. SQLMaps맵핑 파일은 SQLMaps설정파일처럼 전체적인 구조를 볼 필요 없이 이후 설명되는 데이터베이스 작업의 종류에 따라 세부적인 부분만을 보도록 하겠다.

    먼저 객체간의 관계는 다음과 같다.

    2.jpg

    SQLMaps를 사용하기 위한 객체 생성

    SQLMaps를 사용하기 위해서 기본적으로 생성해줘야 하는 객체는 SqlMapClient 이다. 이 객체를 생성하기 위해서는 SQLMaps설정파일인 SqlMapsConfig.xml을 인자로 다음과 같이 코드를 작성하면 기본적으로 SQLMaps의 기능을 사용할 수 있는 SQLMapClient 객체가 생성된다. 이 소스는 getSqlMapConfig()라는 메소드이며 반환되는 객체는 이 문서에서 계속 사용된다.

    Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
    SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

    조회

    조회 작업의 경우 크게 한 개의 테이블을 조회하는 단순조회와 여러 개의 테이블이 서로 관계를 가지는 상태에서 조회하는 다중 테이블 조회의 두 가지의 경우로 나누어서 보겠다.

    1. 테이블 한 개의 대한 단순조회

    단순조회의 경우를 보기 위해 일단 사용자 정보를 보는 부분을 살펴보기로 하겠다. 사용자 정보에 해당되는 User.java소스는 위의 클래스다이어그램을 통해 파악을 할 수 있을 것이다.

    다음은 조회를 위해 사용된 SQLMaps맵핑 파일의 일부이다.

    소스 : User.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
    <sqlMap>
      <select id="getUser" parameterClass="string" resultMap="user">
      <![CDATA[
        select 
          user_id as id, 
          password as password, 
          nick_name as nickName
        from userinfo
        where user_id=#id#
      ]]>
      </select>
    </sqlMap>

    dtd문서를 보면 알겠지만 SQL문을 포함할 수 있는 요소는 <statement>, <insert>, <update>, <delete>, <select>, <procedure> 정도가 된다. 각각의 의미는 짐작이 갈 것이다. statement는 모든 SQL문의 형태, insert, update, delete, select는 각각의 데이터베이스 작업, procedure는 프로시저작업을 할때 사용하면 된다. 일단 여기서는 조회작업을 수행하기 때문에 <select>를 사용했다. 속성으로는 id, parameterClass, resultClass가 사용되었는데 id 속성 값은 자바소스에서 해당 쿼리를 참조하기 위한 키의 역할을 담당한다. 키에 대해서는 이 xml 뒤에 나오는 자바소스를 통해 좀 더 자세히 설명할 것이다. parameterClass 속성값이 string이면 인자로 넘어오는 값이 문자열타입임을 나타낸다. 즉 user_id에는 인자로 넘어오는 문자열값이 자동으로 셋팅된다. resultClass속성값인 user는 조회 후 각각의 레코드가 자동으로 user객체 타입으로 생성이 된다는 것을 의미한다. 여기서 user라는 값은 앞에서 별칭된 net.openseed.orm.openboard.domain.User를 나타낸다. 내부적으로는 user객체가 생성이 되서 각각의 칼럼의 값이 setId(id칼럼값), setPassword(password칼럼값), setNickName(nickName칼럼값)를 차례로 호출하여 값을 할당하게 되는 셈이다.

    이렇게 내부적으로 처리가 된다면 DAO계층에서 개발자가 어떻게 코딩을 하면 될까.? 그 형식은 다음과 같다.

        public User get(String id) {
            SqlMapClient sqlMap = null;
            User user = null;

            try {
                sqlMap = getSqlMapConfig();
                user = (UsersqlMap.queryForObject("getUser", id);
            catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return user;
        }

    단순히 소스코드에서 SQL문과 자바소스만 분리한 것 같은데도 너무 간단하지 않은가.? 사실. 예제의 SQL문 자체가 너무 단순해서 간단함이 잘 느껴지지 않을 수 있으나 테이블 자체가 굉장히 많은 칼럼을 가지고 있었던 예전 경험을 생각해 보라. 이것은 사용자로 하여 SQLMaps를 사용하면 굉장히 지겨운 JDBC코드작성에서 벗어나고 그 과정에서 발생할 수 있는 많은 버그도 줄일 수가 있을 것이다.

    2. 두개이상의 테이블에 대한 조회

    그렇다면 다른 테이블과 1:1, 1:M, 또는 M:N 등의 다중 관계를 가지는 경우에는 어떻게 처리할까.? 그 예는 메시지관련 부분을 보면 된다. Message는 게시판에서 사용자에게 보여지게 되는 실제 글에 해당되는 객체로써 Message.java를 사용한다.

    이러한 관계를 SQLMaps맵핑 파일에서는 어떻게 표현할까.? 그 표현방식은 다음에서 볼 수 있다.

    소스 : Message.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
    <sqlMap namespace="Message">
      <resultMap id="get-message" class="message">
        <result property="id" column="id"/>
        <result property="subject" column="subject"/>
        <result property="content" column="content"/>
        <result property="hitCount" column="hitCount"/>
        <result property="logTime" column="logTime"/>
      </resultMap>
      <resultMap id="get-message-result" class="message" extends="get-message">
        <result property="user.id" column="user_id"/>
        <result property="user.password" column="password"/>
        <result property="user.nickName" column="nickName"/>
        <result property="comments" column="{id=id}" select="getCommentList" />
      </resultMap>

      <select id="getMessageList" resultMap="get-message-result">
      <![CDATA[
        select a.seq as id,
          a.subject as subject,
          a.content as content,
          a.user_id as user_id,
          a.hit_count as hitCount,
          a.log_time as logTime,
          b.password as password,
          b.nick_name as nickName
        from message a, userinfo b
        where a.user_id=b.user_id
        order by a.seq desc
      ]]>
      </select>
    </sqlMap>

    여기서 눈여겨보아야 하는 것은 resultMap이다. 이는 복합적인 타입을 사용할 때 굉장히 유용하다. 물론 복합타입에만 사용할 필요는 없지만 필자는 기본적으로 복합타입이 아닐 경우 resultClass를 사용한다. 여기에서 첫 번째 resultMap은 기본적인 message정보를 가진다. 두 번째는 짐작할 수 있듯이 메시지 객체의 사용자정보와 여러 개의 덧글에 대한 정보를 가진다. 여기서 두번째 resultMap은 첫번째 resultMap의 정보를 가져오기 위해 extends 속성을 사용한다. 즉 extends는 두개의 resultMap를 연결하는 연결자 역할을 하게 된다. 이 resultMap에는 내포된 객체에 값을 셋팅하는 방법도 포함하고 있다. <result property="user.id" column="user_id"/> 여기서 property값인 user.id가 셋팅될 객체의 프라퍼티를 가리킨다. 다시 말해 Message객체내의 user객체의 id값을 user_id칼럼의 값으로 셋팅하는 것이다. 굳이 자바 소스로 표현해 본다면 다음과 같을 것이다. message.getUser().setId( rs.getString("user_id") ); 이런 처리방식으로 내포된 다양한 객체에 대한 접근도 가능하다. 그렇다면 메시지 객체내의 여러 개의 덧글을 의미하는 Collection형태의 객체는 어떻게 생성할까.? 그 방법은 <result property="comments" column="{id=id}" select="getCommentList" /> 에 모두 담겨있다. 여기서는 두 가지가 설명되어야 한다. 먼저 select값인데 이는 getCommentList라는 id값을 가지는 쿼리를 호출한다. getCommentList라는 id값을 가지는 쿼리는 다음과 같다.

    소스 : Comment.xml

       <select id="getCommentList" parameterClass="comment" resultMap="get-comment-result">
      <![CDATA[
        select cu.seq as seq, 
          cu.content as content, 
          cu.log_time as logTime,
          cu.user_id as userId, 
          cu.message_seq as messageSeq, 
          cu.nick_name as nickName,
          cu.password as password, 
          m.seq as mseq,
          m.subject as subject, 
          m.content as mcontent,
          m.user_id as muserId, 
          m.hit_count as hitCount, 
          m.log_time as mlogTime
          from (select c.seq, c.content,
          c.log_time, c.user_id, c.message_seq,
          u.nick_name, u.password
        from comment c, userinfo u
        where c.user_id=u.user_idcu, message m
        where cu.message_seq=m.seq
        and cu.message_seq=#id#
        order by cu.seq asc
      ]]>
      </select>
    ]]>
    </select>

    이 쿼리는 실제 Comment.xml이라는 xml파일에 있는데 SQLMaps맵핑파일이 SQLMaps설정파일에 모두 선언이 되어 있다면 각각의 맵핑파일내 SQL문은 어디서든 호출이 가능하다. 이것은 굉장히 큰 장점이다. 해당 SQL문이 xml내에서 뿐 아니라 자바소스내에서도 어디서든 호출된다는 것은 해당 테이블의 구조가 변경될시 기존의 JDBC형태의 프로젝트처럼 프로그램마다 쿼리문을 수정했던 어려움 없이 해당 맵핑 파일의 SQL문 하나만을 수정하면 전체 프로그램에 반영이 된다는 것이다. 필자는 독자 여러분이 이런 부분을 정말 큰 장점이라고 인식해주길 바란다. select="getCommentList"을 사용함으로써 자동적으로 <result>에는 List형태의 값이 자동으로 셋팅된다. 그럼 많은 독자분들이 조회조건에 해당되는 값은 어떻게 넘겨야 하는지에 대한 의문이 들것이다. 이에 대한 답은 column속성에 모두 담겨있다. 지금 이 소스의 column값은 {id=id} 이다. 이것은 특정객체의 id값을 id칼럼의 값으로 셋팅한다는 것이다. 즉 {id=id}에서 전자의 id는 값이 셋팅되는 객체의 id라는 변수이고 후자의 id는 id칼럼의 값이다. 결과적으로 현재 getCommentList쿼리의 parameterClass인 comment객체의 id값을 id칼럼의 값으로 셋팅해서 넘기게 된다. 만약에 두개 이상의 조회조건, 예를 들면 comment객체의 id값과 content값을 인자로 넘겨야 한다면 ,(콤마)를 구분자로 주어서 {id=id,content=content} 형태로 column값을 설정하면 된다. 지금까지 설명한 것은 getCommentList의 parameterClass가 원시타입이 아닌 특정객체타입 일때의 경우이고 단순히 원시타입인 string이나 int타입이라면 column값을 id 라고 지정해 주면 된다. 즉 칼럼명만 지정해주면 된다. 이는 id칼럼값을 그냥 그대로 넘기는 것을 의미한다. 결과적으로 id가 getMessageList인 SQL문을 호출하면 메시지에 관련된 값이 자동으로 get-message-result라는 값의 resultMap에 셋팅되고 이에 자동적으로 다시 getCommentList를 호출해서 해당 값을 다시 Collection형태의 값으로 채워준다.

    자바소스에서의 처리는 다음과 같다.

    PaginatedList list = (PaginatedListsqlMap.queryForPaginatedList("getMessageList""", range);
    for (int i = 0; i < page - 1; i++) {
      list.nextPage();
    }

    여기서 queryForPaginatedList 메소드는 SQLMaps에서 페이지처리를 위해 기본으로 제공하는 메소드이다. 이것을 사용하면 페이지처리를 자동으로 해준다. 조회는 이렇게 두 가지 경우만 살펴보면 거의 대부분의 상황에 대해 설명이 되는 듯 하다. 그럼 입력의 경우를 살펴보도록 하자.

    입력

      <insert id="insertMessage" parameterClass="message">
        <selectKey resultClass="int" keyProperty="id">
        <![CDATA[
          select nextval('hibernate_sequence');
        ]]>
        </selectKey>
      <![CDATA[
        insert into message(seq, subject, content, user_id, hit_count, log_time)
        values(#id#, #subject#, #content#, #user.id#, 0'today')  
      ]]>
      </insert>

    입력 또한 조회의 경우와 크게 다르지 않다. parameterClass에 해당되는 객체의 값이 각각의 #값# 에 셋팅된다. 조회의 경우와 다르게 추가되는 부분은 <selectKey>요소이다. 이 요소는 선택사항으로 key에 해당되는 값을 임의로 조회결과값으로 설정할 수가 있도록 지원하는 기능을 가진다. 즉 selectKey내의 쿼리문에 의해 반환되는 값이 #id#값에 대치가 된다는 것이다.

    자바소스 내에서는 다음과 같이 처리할 수 있다.

            try {
                sqlMap = getSqlMapConfig();
                sqlMap.startTransaction();

                result = (IntegersqlMap.insert("insertMessage", message);

                sqlMap.commitTransaction();
                success = true;
            catch (NestedException ne) {
                logger.error(ne.getMessage(), ne);
            catch (Exception e) {
                logger.error(e.getMessage(), e);
            finally {
                sqlMap.endTransaction();
            }

    이 소스의 insert()메소드는 결국 다음과 같은 작업을 수행하는 셈이다.

    String sql = "insert into message(seq, subject, content, user_id, hit_count, log_time)
    values(?, ?, ?, ?, 0, 'today')"
    PreparedStatement pstmt = connection.prepareStatement(sql);
    pstmt.setString(1, message.getId());
    pstmt.setString(2, message.getSubject());
    pstmt.setString(3, message.getContent());
    pstmt.setString(4, message.getUser().getId());
    result = pstmt.executeUpdate();

    여기서 필자는 추가적으로 SQLMaps내에서의 트랜잭션 처리에 대해서 언급하도록 하겠다. SQLMaps의 트랜잭션은 sqlMap.startTransaction() 메소드를 호출함으로써 시작된다. 커밋을 수행하기 위해서는 sqlMap.commitTransaction() 메소드를 호출하면 된다. 하지만 SQLMaps API를 잠시 들여다 보면 SQLMaps에는 롤백에 관련된 메소드가 없다. 아니 없다기 보단 임의로 롤백을 수행하는 메소드가 없다. SQLMaps에서는 예외가 발생할 경우 sqlMap.endTransaction()메소드를 호출함으로써 롤백을 수행할 수 있다. 즉 sqlMap.endTransaction()은 정상적으로 모든 작업이 수행이 되면 트랜잭션을 커밋하고 connection을 닫는 작업을 자동으로 수행하게 되고 만약 예외가 발생했을 경우 트랜잭션을 롤백하고 connection을 닫는 작업을 자동으로 수행한다.

    이런 트랜잭션처리를 하더라도 결과적으로 제대로 트랜잭션처리가 안되는 경우가 있다. MySQL예전 버전(필자가 테스트한 바로는 4.0.x버전)에서는 정상적인 처리가 되지 않고 각각의 작업이 수행 직후 바로 커밋되어버린다. 이는 iBATIS에서도 공식적으로 알려진 부분이고 다른 데이터베이스나 MySQL 4.1.x버전을 포함한 이후버전에서는 문제가 없다.

    수정과 삭제의 작업은 입력의 작업과 사실 거의 유사하다. 그래서 수정과 삭제에 대한 추가적인 설명은 여기서 생략하도록 하겠다.

    Spring에서 SQLMaps 사용하기.

    Spring은 현재 비즈니스 레이어를 담당하는 오픈소스 프레임워크중에 거의 독보적인 위치를 차지하고 있다. Spring을 사용하면 IoC형태로 트랜잭션을 관리할 수도 있고 SQLMaps를 좀더 쉽게 사용할 수 있도록 도와준다.

    Spring에서는 SQLMaps 1.x와 2.x를 지원하기 위한 클래스가 다르다. 물론 xml설정파일에서 셋팅하는 값이 다르다. 여기서는 2.x버전을 지원하는 내용만을 다룬다.

    SqlMapConfig.xml을 applicationContext.xml으로 옮기기

    소스 : applicationContext.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <!-- 이 설정파일은 openseed의 스터디때 생성된 파일이 아니다. 
    글을 설명하기 위해 임의로 생성된 파일이나 설정자체는 제대로 작동하는것을 확인했다. -->
    <beans>
      <!-- iBATIS SQLMaps의 설정파일 위치를 지정한다. 
      
      class값은 
      SQLMaps 1.x버전을 사용할때는 org.springframework.orm.ibatis.SqlMapFactoryBean
      SQLMaps 2.x버전을 사용할때는 org.springframework.orm.ibatis.SqlMapClientFactoryBean 를 사용한다.
      -->
      <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation"><value>WEB-INF/SqlMapConfig.xml</value></property>
      </bean>

      <!-- dataSource를 사용하는것에 대한 정보를 나타낸다. 
      여기서 사용될수 있는 dataSource타입은 다른 문서를 참조하길 바란다. 
      
      여기선 apache의 DBCP Connection pooling을 사용하는 것이다. -->
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>org.postgresql.Driver</value></property>
        <property name="url"><value>jdbc:postgresql://localhost:5432/openseed</value></property>
        <property name="username"><value>openseed</value></property>
        <property name="password"><value>openseed</value></property>
        <property name="defaultAutoCommit"><value>false</value></property>
      </bean>
      
      <!-- DB연결에 관련된 설정을 DataSource형태로 지정을 했기 때문에 트랜잭션 관리를 
      org.springframework.jdbc.datasource.DataSourceTransactionManager 가 담당하도록 지정한다. -->
      <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource"><ref local="dataSource"/></property>
      </bean>  
      
      <!-- 각각의 메소드 별로 트랜잭션관리 속성을 지정한다. -->
      <bean id="guestService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
        <property name="transactionManager"><ref local="myTransactionManager"/></property>
        <property name="target"><ref local="guestTarget"/></property>
        <property name="transactionAttributes">
          <props>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="save*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
          </props>
        </property>
      </bean>  
      
      <!-- 소위 Spring을 사용하게 되는 비지니스 객체의 클래스를 지정하는 부분이다. 
      즉 여기선 gikim.dongguk.guestboard.spring.GuestSpringImpl 클래스가 Spring의 여러가지 기능을 담당하게 되는것이다.
      그리고 관리하게 되는 DAO는 guestDAO로 지정한다. 
      -->
      <bean id="guestTarget" class="gikim.dongguk.guestboard.spring.GuestSpringImpl">
        <property name="guestDAO"><ref local="guestDAO"/></property>
      </bean>  
      
      <!-- DAO에 관련된 셋팅이다. 실제로 iBATIS SQLMaps를 사용하게 되는 클래스를 지정하게 된다. 
      DB정보인 dataSource값과. iBATIS SQLMaps설정파일의 위치에 해당하는 sqlMapClient를 지정한다. 
      -->
      <bean id="guestDAO" class="gikim.dongguk.guestboard.dao.IbatisGuestDAOImpl">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="sqlMapClient"><ref local="sqlMapClient"/></property>
      </bean>
    </beans>

    SqlMapConfig.xml의 내용을 applicationContext.xml 로 옮기면 사실 SqlMapConfig.xml에는 <settings>와 <sqlMap>요소만 정의를 해주면 된다. 기존의 <properties>와 <typeAlias>, <transactionManager> 는 applicationContext.xml의 내용으로 대체되는 것이다. 그 외의 SQLMaps맵핑 파일 같은 경우는 그대로 사용가능하다.

    SqlMapClient 객체를 대체하는 SqlMapClientTemplate

    spring은 SqlMapClient객체를 대체하는 SqlMapClientTemplate를 제공하는데 이를 생성하는 메소드는 getSqlMapClientTemplate()이다.

    Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
    SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
    user = (UsersqlMap.queryForObject("getUser", id);

    사용자 정보를 가져오는 소스가 위와 같다고 할 때 spring의 SqlMapClientTemplate를 사용하면 아래와 같이 될 것이다..

    User user = getSqlMapClientTemplate().queryForObject("getUser", id);

    눈에 띄게 소스가 간편해진다. 이것밖에 장점이 없을까.? 아니다. 다음의 소스를 보자. spring이 자동적으로 트랜잭션을 처리해 주기 때문에 조금 전 입력예제로 사용되었던 소스가 아래처럼 다시 변경될 수 있다.

    getSqlMapClientTemplate().insert("insertMessage", message);
    return true;

    spring의 트랜잭션 관리를 사용하면 위와 같이 소스가 간단해진다.

    이것은 transactionAttributes 속성 하위의 설정값들에 의해 spring의 DI(dependency injection)을 사용하여 가능한 것이지만, 일단 개발자들에게는 SQLMaps로 인해 간단해진 소스가 더욱 심플해졌다는 사실 자체로 행복한 일일 것이다. 이건 개발 프레임워크를 제대로 사용할 때 개발 프레임워크가 개발자에게 주는 혜택이다.

    결과적으로 SQLMaps는

    지금까지의 설명에서 SQLMaps는 기존의 JDBC프로그래밍 방식과 근본적으로 프로그래밍 방식이 바뀌는 건 아님을 알 수 있다. 사실 이런 부분이 기존의 코딩 방식을 그대로 가져가기 때문에 획기적인 개선이 없다는 단점을 낳기도 한다. 개인적으로 SQLMaps는 JDBC프로그래밍 방식과 hibernate와 같은 완전히 다른 방식의 데이터베이스 처리 방식 사이의 중간에 위치한다고 생각한다. 둘의 단점을 모두 가지고 있지만 둘의 장점 또한 모두 가지고 있는 ORM이다. 그 둘의 단점을 피하고 장점만을 제대로 사용한다면 정말 좋은 ORM이라는 건 어느 누구도 의심하지 않을 것이다. 필자는 다음과 같은 경우에 hibernate보다는 SQLMaps가 적합할 것 같다고 생각을 한다.

    • JDBC코딩의 단점은 버리고 싶으나 hibernate와 같은 전혀 다른 방식을 사용하는 것은 부담스러운 프로젝트
    • 기존 JDBC형태의 프로젝트를 ORM 기술을 사용해서 변경하고자 할 때
    • 데이터베이스에 관련된 DBA가 회사 내에 있어서 기존의 SQL에 대한 지식과 경험이 많거나 HQL의 성능이 의심되는 경우

    개발자는 SQLMaps의 설정방법과 맵핑파일에 관련된 몇몇 지식만 가지면 기존의 JDBC방식을 사용하던 개발자가 SQLMaps를 사용하는 건 크게 어렵지 않다. 하지만 JDBC 코드를 SQLMaps로 바꾸었을 때의 결과는 굉장한 긍정적인 차이를 가질 것이라는 점은 위에서 계속 설명했던 바이다

    필자가 설명하는 SQLMaps의 장점이 제대로 전달되었는지는 잘 모르겠다. 사실 이외에도 SQLMaps에서 지원하는 기능은 많다. 물론 여기서 필히 논의가 되었어야 할 dynamic SQL부분이나 로깅관련 사항들은 지면이 모든 내용을 포함하도록 할 수 없는 제한으로 인해 설명되지 못했다. 이 사항들은 관련 문서와 커뮤니티에서 충분한 정보를 얻을 수 있을 것이다. 현재 가장 빠르게 발전하고 있는 ORM은 hibernate임에는 필자도 이견을 달지 않는다. 하지만 오픈소스가 생성된 배경과 의도가 다른 만큼 개발자들이 단순히 기술적인 부분에만 치우쳐 오픈소스를 사용하는 일은 없었으면 한다. 기술적인 부분이 어느 정도 지원하는 수준에서 프로젝트에서 요구하는 상황과 해당 오픈소스의 생성의도가 제대로 맞아떨어질 때 그 오픈소스가 정말 강력한 기능을 발휘할 것이라는 점은 모두가 동의할 것이다. 현재 hibernate는 jboss의 지원을 받고 있고 SQLMaps는 아파치의 지원을 받고 있다. 두 오픈소스가 충분히 발전할 가능성을 가지고 있고 이미 강력한 기능을 지원하는 만큼 적재적소에 해당 오픈소스를 사용하길 바란다.

    참고자료

    iBATIS 홈페이지 - http://incubator.apache.org/ibatis/site/index.html
    SQLMaps 2.0개발자 가이드(한글) http://openframework.or.kr/JSPWiki/attach/Hibernate/iBATIS-SqlMaps-2_ko.pdf
    SQLMaps 2.0튜토리얼(한글) http://openframework.or.kr/JSPWiki/attach/Hibernate/iBATIS-SqlMaps-2-Tutorial_ko.pdf
    SQLMaps를 이용한 객체-관계맵핑 http://openframework.or.kr/JSPWiki/Wiki.jsp?page=ObjectRelationalMappingwithSQLMaps
    네이버 자바프레임워크 http://cafe.naver.com/deve
    네이버 자바프레임워크 위키 http://openframework.or.kr

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:17
    반응형



    이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용이며 저작권에 관련한 모든 사항은 마이크로소프트웨어에 있습니다.
    이 문구를 삭제하고 배포시 저작권에 위배될수 있습니다.

    저자 정보 : 이동국(mailto:fromm0@gmail.com)

    현재 울산에 있는 아이티스타에서 근무하고 있으며 주로 현대자동차 관련 프로젝트에 참여하고 있다. 네이버 자바프레임워크 카페 스탭으로 할동하고 있고 오픈프레임워크 사이트를 관리하고 있다. 평소 개발 프레임워크와 웹서비스에 관심을 가지고 있으며 요즘은 AndroMDA에 관련해서 공부를 시작했다.

    ORM의 또 다른 핵 iBATIS SQLMaps

    작년을 비롯해서 현재까지 해외 자바 관련 커뮤니티에서 가장 많이 논의가 되고 있는 부분 중 하나는 ORM이다. 그 이유를 생각해보면 자바개발의 많은 부분을 차지하고 있는 분야가 웹프로그래밍이고 그 웹프로그래밍의 거의 대부분을 차지하는 분야가 데이터베이스관련 처리이기 때문일 것이다. 현재 그 ORM을 대표하는 두 가지가 있다. 하나는 hibernate이고 또 하나는 이번에 소개할 iBATIS의 SQLMaps이다. 한때 객체와 관계형 데이터베이스의 관계 맵핑을 설정하면 SQL문을 자동 생성해 주는 hibernate에 비해 SQL문 자동 생성 기능이 없는 SQLMaps는 진정한 의미의 ORM이 아니다 라는 분위기도 있었지만 관계형 데이터베이스와 통신할 수 있는 유일한 매개체인 SQL문과 객체를 맵핑 시켜준다는 의미에서 현재는 SQLMaps또한 ORM이라고 보고 있다. hibernate의 경우 자바 관련 커뮤니티에서 많이 다루어 진 것으로 알고 있다. 우리는 여기서 SQLMaps에 대해서 알아보고자 한다. SQLMaps의 장점은 무엇일까.? iBATIS에서 밝히는 SQLMaps의 최대 장점은 간단함(simple)이다. 이것은 필자를 포함한 SQLMaps를 사용한 대부분의 개발자들이 인정하는 부분이다. 그 간단함이란 기존의 SQL문을 별다른 수정 없이 그대로 사용할 수 있는 상황에서 단순히 객체와 SQL문의 맵핑을 위한 몇몇 설정값만 설정해 주면 간단하게 ORM의 기능을 경험해 볼 수 있다는 것이다. 이러한 장점은 단순한 설명만으로는 잘 느껴지지 않으리라 본다. 잠시 후 예제를 통해서 정말 SQLMaps가 기존의 JDBC프로그램에 비해 얼마나 간단하게 구현이 되는지 보자.

    SQLMaps는

    앞에서 필자가 SQLMaps는 SQL과 객체를 맵핑시켜주는 도구라고 소개했지만 사실 엄밀하게 따지면 자바빈즈를 PreparedStatement 파라미터와 ResultSet으로 맵핑시켜주는 기능을 담당한다. 즉 PreparedStatement의 ? 에 각각의 파라미터 값을 setString()과 같은 메소드를 사용해서 셋팅하는 과정이나 ResultSet에서 getString()과 같은 메소드를 통해서 임의의 VO객체를 생성하는 과정을 자동으로 해준다. 결과적으로 간단한 xml셋팅만으로 일일이 손으로 작성하던 기존 JDBC형식을 버릴 수가 있다. SQLMaps의 구조를 도식화하면 다음과 같다.

    1.jpg

    iBATIS에서는 결과적으로 기존 데이터베이스 프로그램 코드의 20%정도만 사용해도 80%이상의 같은 기능을 수행할 수가 있게 된다고 밝히고 있고 필자 또한 그렇게 생각하고 있다.

    이론적인 설명은 이쯤에서 잠시 접어두고 실제 사용하는 것을 보고 과연 어떻게 다른가를 알아보자. 아래의 소스는 얼마 전 오픈시드 프로젝트(http://openseed.net)의 ORM 연구회에서 진행한 1차 테스트 프로젝트의 소스이다. 일단 SQLMaps를 사용하기 위해서는 최소 두 가지의 설정파일이 필요하다. SQLMaps 설정파일과 SQLMaps 맵핑 파일이다. 추가적으로 프라퍼티값을 외부로 빼내기 위해서 사용되는 properties파일이 필요할 수 도 있다. 먼저 SQLMaps설정 파일인 SqlMapsConfig.xml을 보자.

    SQLMaps 설정파일

    소스 : SqlMapConfig.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" 
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
    <sqlMapConfig>
       <properties resource="SqlMapConfig.properties" />

       <settings cacheModelsEnabled="true" enhancementEnabled="true"
    lazyLoadingEnabled="true" maxRequests="32" 
    maxSessions="10" maxTransactions="5" 
    useStatementNamespaces="false" />

       <typeAlias alias="comment" type="net.openseed.orm.openboard.domain.Comment"/>
       <typeAlias alias="message" type="net.openseed.orm.openboard.domain.Message"/>
       <typeAlias alias="user" type="net.openseed.orm.openboard.domain.User"/>

       <transactionManager type="JDBC">
          <dataSource type="DBCP">
             <property name="JDBC.Driver" value="${driver}" />
             <property name="JDBC.ConnectionURL" value="${url}" />
             <property name="JDBC.Username" value="${username}" />
             <property name="JDBC.Password" value="${password}" />
             <property name="JDBC.DefaultAutoCommit" value="false" />
          </dataSource>
       </transactionManager>

       <sqlMap resource="Comment.xml" />
       <sqlMap resource="Message.xml" />
       <sqlMap resource="User.xml" />
    </sqlMapConfig>

    xml파일 내용을 보면 크게 5가지로 분류되어 있다. 첫 번째인 <properties>는 프라퍼티값을 외부로 빼내서 사용하기 위해 프라퍼티파일을 사용할 때 해당 프라퍼티파일의 경로를 지정해준다. 프라퍼티 파일은 ‘키=값’ 의 형태로 값을 지정하고 SqlMapConfig.xml에서는 ${키} 의 형태로 사용할 수 있다.

    두 번째인 <settings>은 SQLMaps에서 사용되는 다양한 옵션과 최적화를 위한 값들이다. 각각의 값들은 다음의 표를 참조하길 바란다.

    cacheModelsEnabled SqlMapClient 를 위한 모든 캐시모델을 가능 유무.
    Default: true (enabled)
    enhancementEnabled 런타임시 바이트코드 향상을 가능유무.
    Default: false (disabled)
    lazyLoadingEnabled 모든 늦은(lazy)로딩을 가능유무.
    Default: true (enabled)
    maxRequests 동시에 SQL문을 수행할 수 있는 쓰레드의 수. 셋팅값보다 많은 쓰레드는 다른 쓰레드가 수행을 완료할 때까지 블록 된다.
    Default: 512
    maxSessions 주어진 시간동안 활성화될 수 있는 세션의 수.
    Default: 128
    maxTransactions 한꺼번에 SqlMapClient.startTransaction()에 들어갈 수 있는 쓰레드의 최대갯수. 셋팅값보다 많은 쓰레드는 다른 쓰레드가 나올 때까지 블록 된다.
    Default: 32
    useStatementNamespaces 이 셋팅을 가능하게 하면 당신은 sqlmap이름과 statement이름으로 구성된 전체적인 이름(fully qualified name)으로 맵핑된 statement를 참조해야 한다.
    예를 들면: queryForObject("sqlMapName.statementName");
    Default: false (disabled)

    세 번째인 <typeAlias>는 패키지 명을 포함한 클래스가 너무 길 때 각각의 SQLMaps맵핑 파일에서 사용하기 번거로우므로 별칭을 두어서 간단하게 사용할 수 있다. 하지만 미리 정의된 별칭이 있다. 그 값들은 다음과 같다.

    transactionManager에서 사용되는 별칭
    JDBC com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig
    JTA com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig
    EXTERNAL com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
    dataSource에서 사용되는 별칭
    SIMPLE com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
    DBCP com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
    JNDI com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory

    네 번째인 <transactionManager>는 트랜잭션에 관련된 값을 셋팅하고 하위 데이터소스값을 지정하는 <dataSource>를 가진다. transactionManager의 type속성 값은 JDBC, JTA, EXTERNAL 중에 하나를 사용할 수 있는데 그 각각의 값은 다음과 같은 특징을 가진다.

    • JDBC - Connection commit()과 rollback()메소드를 통해 트랜잭션을 제어하기 위한 JDBC를 사용하게 된다.
    • JTA - 이 트랜잭션관리자는 SQL Maps가 다른 데이터베이스나 트랜잭션 자원을 포함하는 더욱 넓은 범위의 트랜잭션을 포함하도록 하는 JTA전역트랜잭션를 사용한다.
    • EXTERNAL - 이것은 개발자가 직접 트랜잭션을 관리할 때 사용하는 것으로 주로 분산 컴포넌트 기반 시스템 환경에서 컨테이너가 트랜잭션을 관리하는 경우에 사용된다.

    dataSource의 type속성 값은 SIMPLE, DBCP, JNDI 중에 하나를 사용할 수 있다. 이 값은 각각 iBATIS SimpleDataSource 커넥션 풀링, Jakarta DBCP, JNDI를 통한 데이터소스을 사용하게 한다.

    다섯 번째인 <sqlMap>은 SQLMaps맵핑 파일의 위치를 지정한다. resource속성 값에 전체패키지경로명을 포함하는 클래스 명을 써주면 된다.

    기본이 되는 SQLMaps의 설정파일은 이렇게 특별히 어려운 설정 없이 간단하게 설정할 수 있다. 그럼 이제부터는 데이터베이스 작업별로 SQLMaps를 어떻게 사용하는지 보여주기 위한 요소인 자바소스와 SQLMaps맵핑 파일을 보도록 하자. SQLMaps맵핑 파일은 SQLMaps설정파일처럼 전체적인 구조를 볼 필요 없이 이후 설명되는 데이터베이스 작업의 종류에 따라 세부적인 부분만을 보도록 하겠다.

    먼저 객체간의 관계는 다음과 같다.

    2.jpg

    SQLMaps를 사용하기 위한 객체 생성

    SQLMaps를 사용하기 위해서 기본적으로 생성해줘야 하는 객체는 SqlMapClient 이다. 이 객체를 생성하기 위해서는 SQLMaps설정파일인 SqlMapsConfig.xml을 인자로 다음과 같이 코드를 작성하면 기본적으로 SQLMaps의 기능을 사용할 수 있는 SQLMapClient 객체가 생성된다. 이 소스는 getSqlMapConfig()라는 메소드이며 반환되는 객체는 이 문서에서 계속 사용된다.

    Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
    SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

    조회

    조회 작업의 경우 크게 한 개의 테이블을 조회하는 단순조회와 여러 개의 테이블이 서로 관계를 가지는 상태에서 조회하는 다중 테이블 조회의 두 가지의 경우로 나누어서 보겠다.

    1. 테이블 한 개의 대한 단순조회

    단순조회의 경우를 보기 위해 일단 사용자 정보를 보는 부분을 살펴보기로 하겠다. 사용자 정보에 해당되는 User.java소스는 위의 클래스다이어그램을 통해 파악을 할 수 있을 것이다.

    다음은 조회를 위해 사용된 SQLMaps맵핑 파일의 일부이다.

    소스 : User.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
    <sqlMap>
      <select id="getUser" parameterClass="string" resultMap="user">
      <![CDATA[
        select 
          user_id as id, 
          password as password, 
          nick_name as nickName
        from userinfo
        where user_id=#id#
      ]]>
      </select>
    </sqlMap>

    dtd문서를 보면 알겠지만 SQL문을 포함할 수 있는 요소는 <statement>, <insert>, <update>, <delete>, <select>, <procedure> 정도가 된다. 각각의 의미는 짐작이 갈 것이다. statement는 모든 SQL문의 형태, insert, update, delete, select는 각각의 데이터베이스 작업, procedure는 프로시저작업을 할때 사용하면 된다. 일단 여기서는 조회작업을 수행하기 때문에 <select>를 사용했다. 속성으로는 id, parameterClass, resultClass가 사용되었는데 id 속성 값은 자바소스에서 해당 쿼리를 참조하기 위한 키의 역할을 담당한다. 키에 대해서는 이 xml 뒤에 나오는 자바소스를 통해 좀 더 자세히 설명할 것이다. parameterClass 속성값이 string이면 인자로 넘어오는 값이 문자열타입임을 나타낸다. 즉 user_id에는 인자로 넘어오는 문자열값이 자동으로 셋팅된다. resultClass속성값인 user는 조회 후 각각의 레코드가 자동으로 user객체 타입으로 생성이 된다는 것을 의미한다. 여기서 user라는 값은 앞에서 별칭된 net.openseed.orm.openboard.domain.User를 나타낸다. 내부적으로는 user객체가 생성이 되서 각각의 칼럼의 값이 setId(id칼럼값), setPassword(password칼럼값), setNickName(nickName칼럼값)를 차례로 호출하여 값을 할당하게 되는 셈이다.

    이렇게 내부적으로 처리가 된다면 DAO계층에서 개발자가 어떻게 코딩을 하면 될까.? 그 형식은 다음과 같다.

        public User get(String id) {
            SqlMapClient sqlMap = null;
            User user = null;

            try {
                sqlMap = getSqlMapConfig();
                user = (UsersqlMap.queryForObject("getUser", id);
            catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return user;
        }

    단순히 소스코드에서 SQL문과 자바소스만 분리한 것 같은데도 너무 간단하지 않은가.? 사실. 예제의 SQL문 자체가 너무 단순해서 간단함이 잘 느껴지지 않을 수 있으나 테이블 자체가 굉장히 많은 칼럼을 가지고 있었던 예전 경험을 생각해 보라. 이것은 사용자로 하여 SQLMaps를 사용하면 굉장히 지겨운 JDBC코드작성에서 벗어나고 그 과정에서 발생할 수 있는 많은 버그도 줄일 수가 있을 것이다.

    2. 두개이상의 테이블에 대한 조회

    그렇다면 다른 테이블과 1:1, 1:M, 또는 M:N 등의 다중 관계를 가지는 경우에는 어떻게 처리할까.? 그 예는 메시지관련 부분을 보면 된다. Message는 게시판에서 사용자에게 보여지게 되는 실제 글에 해당되는 객체로써 Message.java를 사용한다.

    이러한 관계를 SQLMaps맵핑 파일에서는 어떻게 표현할까.? 그 표현방식은 다음에서 볼 수 있다.

    소스 : Message.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
    <sqlMap namespace="Message">
      <resultMap id="get-message" class="message">
        <result property="id" column="id"/>
        <result property="subject" column="subject"/>
        <result property="content" column="content"/>
        <result property="hitCount" column="hitCount"/>
        <result property="logTime" column="logTime"/>
      </resultMap>
      <resultMap id="get-message-result" class="message" extends="get-message">
        <result property="user.id" column="user_id"/>
        <result property="user.password" column="password"/>
        <result property="user.nickName" column="nickName"/>
        <result property="comments" column="{id=id}" select="getCommentList" />
      </resultMap>

      <select id="getMessageList" resultMap="get-message-result">
      <![CDATA[
        select a.seq as id,
          a.subject as subject,
          a.content as content,
          a.user_id as user_id,
          a.hit_count as hitCount,
          a.log_time as logTime,
          b.password as password,
          b.nick_name as nickName
        from message a, userinfo b
        where a.user_id=b.user_id
        order by a.seq desc
      ]]>
      </select>
    </sqlMap>

    여기서 눈여겨보아야 하는 것은 resultMap이다. 이는 복합적인 타입을 사용할 때 굉장히 유용하다. 물론 복합타입에만 사용할 필요는 없지만 필자는 기본적으로 복합타입이 아닐 경우 resultClass를 사용한다. 여기에서 첫 번째 resultMap은 기본적인 message정보를 가진다. 두 번째는 짐작할 수 있듯이 메시지 객체의 사용자정보와 여러 개의 덧글에 대한 정보를 가진다. 여기서 두번째 resultMap은 첫번째 resultMap의 정보를 가져오기 위해 extends 속성을 사용한다. 즉 extends는 두개의 resultMap를 연결하는 연결자 역할을 하게 된다. 이 resultMap에는 내포된 객체에 값을 셋팅하는 방법도 포함하고 있다. <result property="user.id" column="user_id"/> 여기서 property값인 user.id가 셋팅될 객체의 프라퍼티를 가리킨다. 다시 말해 Message객체내의 user객체의 id값을 user_id칼럼의 값으로 셋팅하는 것이다. 굳이 자바 소스로 표현해 본다면 다음과 같을 것이다. message.getUser().setId( rs.getString("user_id") ); 이런 처리방식으로 내포된 다양한 객체에 대한 접근도 가능하다. 그렇다면 메시지 객체내의 여러 개의 덧글을 의미하는 Collection형태의 객체는 어떻게 생성할까.? 그 방법은 <result property="comments" column="{id=id}" select="getCommentList" /> 에 모두 담겨있다. 여기서는 두 가지가 설명되어야 한다. 먼저 select값인데 이는 getCommentList라는 id값을 가지는 쿼리를 호출한다. getCommentList라는 id값을 가지는 쿼리는 다음과 같다.

    소스 : Comment.xml

       <select id="getCommentList" parameterClass="comment" resultMap="get-comment-result">
      <![CDATA[
        select cu.seq as seq, 
          cu.content as content, 
          cu.log_time as logTime,
          cu.user_id as userId, 
          cu.message_seq as messageSeq, 
          cu.nick_name as nickName,
          cu.password as password, 
          m.seq as mseq,
          m.subject as subject, 
          m.content as mcontent,
          m.user_id as muserId, 
          m.hit_count as hitCount, 
          m.log_time as mlogTime
          from (select c.seq, c.content,
          c.log_time, c.user_id, c.message_seq,
          u.nick_name, u.password
        from comment c, userinfo u
        where c.user_id=u.user_idcu, message m
        where cu.message_seq=m.seq
        and cu.message_seq=#id#
        order by cu.seq asc
      ]]>
      </select>
    ]]>
    </select>

    이 쿼리는 실제 Comment.xml이라는 xml파일에 있는데 SQLMaps맵핑파일이 SQLMaps설정파일에 모두 선언이 되어 있다면 각각의 맵핑파일내 SQL문은 어디서든 호출이 가능하다. 이것은 굉장히 큰 장점이다. 해당 SQL문이 xml내에서 뿐 아니라 자바소스내에서도 어디서든 호출된다는 것은 해당 테이블의 구조가 변경될시 기존의 JDBC형태의 프로젝트처럼 프로그램마다 쿼리문을 수정했던 어려움 없이 해당 맵핑 파일의 SQL문 하나만을 수정하면 전체 프로그램에 반영이 된다는 것이다. 필자는 독자 여러분이 이런 부분을 정말 큰 장점이라고 인식해주길 바란다. select="getCommentList"을 사용함으로써 자동적으로 <result>에는 List형태의 값이 자동으로 셋팅된다. 그럼 많은 독자분들이 조회조건에 해당되는 값은 어떻게 넘겨야 하는지에 대한 의문이 들것이다. 이에 대한 답은 column속성에 모두 담겨있다. 지금 이 소스의 column값은 {id=id} 이다. 이것은 특정객체의 id값을 id칼럼의 값으로 셋팅한다는 것이다. 즉 {id=id}에서 전자의 id는 값이 셋팅되는 객체의 id라는 변수이고 후자의 id는 id칼럼의 값이다. 결과적으로 현재 getCommentList쿼리의 parameterClass인 comment객체의 id값을 id칼럼의 값으로 셋팅해서 넘기게 된다. 만약에 두개 이상의 조회조건, 예를 들면 comment객체의 id값과 content값을 인자로 넘겨야 한다면 ,(콤마)를 구분자로 주어서 {id=id,content=content} 형태로 column값을 설정하면 된다. 지금까지 설명한 것은 getCommentList의 parameterClass가 원시타입이 아닌 특정객체타입 일때의 경우이고 단순히 원시타입인 string이나 int타입이라면 column값을 id 라고 지정해 주면 된다. 즉 칼럼명만 지정해주면 된다. 이는 id칼럼값을 그냥 그대로 넘기는 것을 의미한다. 결과적으로 id가 getMessageList인 SQL문을 호출하면 메시지에 관련된 값이 자동으로 get-message-result라는 값의 resultMap에 셋팅되고 이에 자동적으로 다시 getCommentList를 호출해서 해당 값을 다시 Collection형태의 값으로 채워준다.

    자바소스에서의 처리는 다음과 같다.

    PaginatedList list = (PaginatedListsqlMap.queryForPaginatedList("getMessageList""", range);
    for (int i = 0; i < page - 1; i++) {
      list.nextPage();
    }

    여기서 queryForPaginatedList 메소드는 SQLMaps에서 페이지처리를 위해 기본으로 제공하는 메소드이다. 이것을 사용하면 페이지처리를 자동으로 해준다. 조회는 이렇게 두 가지 경우만 살펴보면 거의 대부분의 상황에 대해 설명이 되는 듯 하다. 그럼 입력의 경우를 살펴보도록 하자.

    입력

      <insert id="insertMessage" parameterClass="message">
        <selectKey resultClass="int" keyProperty="id">
        <![CDATA[
          select nextval('hibernate_sequence');
        ]]>
        </selectKey>
      <![CDATA[
        insert into message(seq, subject, content, user_id, hit_count, log_time)
        values(#id#, #subject#, #content#, #user.id#, 0'today')  
      ]]>
      </insert>

    입력 또한 조회의 경우와 크게 다르지 않다. parameterClass에 해당되는 객체의 값이 각각의 #값# 에 셋팅된다. 조회의 경우와 다르게 추가되는 부분은 <selectKey>요소이다. 이 요소는 선택사항으로 key에 해당되는 값을 임의로 조회결과값으로 설정할 수가 있도록 지원하는 기능을 가진다. 즉 selectKey내의 쿼리문에 의해 반환되는 값이 #id#값에 대치가 된다는 것이다.

    자바소스 내에서는 다음과 같이 처리할 수 있다.

            try {
                sqlMap = getSqlMapConfig();
                sqlMap.startTransaction();

                result = (IntegersqlMap.insert("insertMessage", message);

                sqlMap.commitTransaction();
                success = true;
            catch (NestedException ne) {
                logger.error(ne.getMessage(), ne);
            catch (Exception e) {
                logger.error(e.getMessage(), e);
            finally {
                sqlMap.endTransaction();
            }

    이 소스의 insert()메소드는 결국 다음과 같은 작업을 수행하는 셈이다.

    String sql = "insert into message(seq, subject, content, user_id, hit_count, log_time)
    values(?, ?, ?, ?, 0, 'today')"
    PreparedStatement pstmt = connection.prepareStatement(sql);
    pstmt.setString(1, message.getId());
    pstmt.setString(2, message.getSubject());
    pstmt.setString(3, message.getContent());
    pstmt.setString(4, message.getUser().getId());
    result = pstmt.executeUpdate();

    여기서 필자는 추가적으로 SQLMaps내에서의 트랜잭션 처리에 대해서 언급하도록 하겠다. SQLMaps의 트랜잭션은 sqlMap.startTransaction() 메소드를 호출함으로써 시작된다. 커밋을 수행하기 위해서는 sqlMap.commitTransaction() 메소드를 호출하면 된다. 하지만 SQLMaps API를 잠시 들여다 보면 SQLMaps에는 롤백에 관련된 메소드가 없다. 아니 없다기 보단 임의로 롤백을 수행하는 메소드가 없다. SQLMaps에서는 예외가 발생할 경우 sqlMap.endTransaction()메소드를 호출함으로써 롤백을 수행할 수 있다. 즉 sqlMap.endTransaction()은 정상적으로 모든 작업이 수행이 되면 트랜잭션을 커밋하고 connection을 닫는 작업을 자동으로 수행하게 되고 만약 예외가 발생했을 경우 트랜잭션을 롤백하고 connection을 닫는 작업을 자동으로 수행한다.

    이런 트랜잭션처리를 하더라도 결과적으로 제대로 트랜잭션처리가 안되는 경우가 있다. MySQL예전 버전(필자가 테스트한 바로는 4.0.x버전)에서는 정상적인 처리가 되지 않고 각각의 작업이 수행 직후 바로 커밋되어버린다. 이는 iBATIS에서도 공식적으로 알려진 부분이고 다른 데이터베이스나 MySQL 4.1.x버전을 포함한 이후버전에서는 문제가 없다.

    수정과 삭제의 작업은 입력의 작업과 사실 거의 유사하다. 그래서 수정과 삭제에 대한 추가적인 설명은 여기서 생략하도록 하겠다.

    Spring에서 SQLMaps 사용하기.

    Spring은 현재 비즈니스 레이어를 담당하는 오픈소스 프레임워크중에 거의 독보적인 위치를 차지하고 있다. Spring을 사용하면 IoC형태로 트랜잭션을 관리할 수도 있고 SQLMaps를 좀더 쉽게 사용할 수 있도록 도와준다.

    Spring에서는 SQLMaps 1.x와 2.x를 지원하기 위한 클래스가 다르다. 물론 xml설정파일에서 셋팅하는 값이 다르다. 여기서는 2.x버전을 지원하는 내용만을 다룬다.

    SqlMapConfig.xml을 applicationContext.xml으로 옮기기

    소스 : applicationContext.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <!-- 이 설정파일은 openseed의 스터디때 생성된 파일이 아니다. 
    글을 설명하기 위해 임의로 생성된 파일이나 설정자체는 제대로 작동하는것을 확인했다. -->
    <beans>
      <!-- iBATIS SQLMaps의 설정파일 위치를 지정한다. 
      
      class값은 
      SQLMaps 1.x버전을 사용할때는 org.springframework.orm.ibatis.SqlMapFactoryBean
      SQLMaps 2.x버전을 사용할때는 org.springframework.orm.ibatis.SqlMapClientFactoryBean 를 사용한다.
      -->
      <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation"><value>WEB-INF/SqlMapConfig.xml</value></property>
      </bean>

      <!-- dataSource를 사용하는것에 대한 정보를 나타낸다. 
      여기서 사용될수 있는 dataSource타입은 다른 문서를 참조하길 바란다. 
      
      여기선 apache의 DBCP Connection pooling을 사용하는 것이다. -->
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>org.postgresql.Driver</value></property>
        <property name="url"><value>jdbc:postgresql://localhost:5432/openseed</value></property>
        <property name="username"><value>openseed</value></property>
        <property name="password"><value>openseed</value></property>
        <property name="defaultAutoCommit"><value>false</value></property>
      </bean>
      
      <!-- DB연결에 관련된 설정을 DataSource형태로 지정을 했기 때문에 트랜잭션 관리를 
      org.springframework.jdbc.datasource.DataSourceTransactionManager 가 담당하도록 지정한다. -->
      <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource"><ref local="dataSource"/></property>
      </bean>  
      
      <!-- 각각의 메소드 별로 트랜잭션관리 속성을 지정한다. -->
      <bean id="guestService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
        <property name="transactionManager"><ref local="myTransactionManager"/></property>
        <property name="target"><ref local="guestTarget"/></property>
        <property name="transactionAttributes">
          <props>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="save*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
          </props>
        </property>
      </bean>  
      
      <!-- 소위 Spring을 사용하게 되는 비지니스 객체의 클래스를 지정하는 부분이다. 
      즉 여기선 gikim.dongguk.guestboard.spring.GuestSpringImpl 클래스가 Spring의 여러가지 기능을 담당하게 되는것이다.
      그리고 관리하게 되는 DAO는 guestDAO로 지정한다. 
      -->
      <bean id="guestTarget" class="gikim.dongguk.guestboard.spring.GuestSpringImpl">
        <property name="guestDAO"><ref local="guestDAO"/></property>
      </bean>  
      
      <!-- DAO에 관련된 셋팅이다. 실제로 iBATIS SQLMaps를 사용하게 되는 클래스를 지정하게 된다. 
      DB정보인 dataSource값과. iBATIS SQLMaps설정파일의 위치에 해당하는 sqlMapClient를 지정한다. 
      -->
      <bean id="guestDAO" class="gikim.dongguk.guestboard.dao.IbatisGuestDAOImpl">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="sqlMapClient"><ref local="sqlMapClient"/></property>
      </bean>
    </beans>

    SqlMapConfig.xml의 내용을 applicationContext.xml 로 옮기면 사실 SqlMapConfig.xml에는 <settings>와 <sqlMap>요소만 정의를 해주면 된다. 기존의 <properties>와 <typeAlias>, <transactionManager> 는 applicationContext.xml의 내용으로 대체되는 것이다. 그 외의 SQLMaps맵핑 파일 같은 경우는 그대로 사용가능하다.

    SqlMapClient 객체를 대체하는 SqlMapClientTemplate

    spring은 SqlMapClient객체를 대체하는 SqlMapClientTemplate를 제공하는데 이를 생성하는 메소드는 getSqlMapClientTemplate()이다.

    Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
    SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
    user = (UsersqlMap.queryForObject("getUser", id);

    사용자 정보를 가져오는 소스가 위와 같다고 할 때 spring의 SqlMapClientTemplate를 사용하면 아래와 같이 될 것이다..

    User user = getSqlMapClientTemplate().queryForObject("getUser", id);

    눈에 띄게 소스가 간편해진다. 이것밖에 장점이 없을까.? 아니다. 다음의 소스를 보자. spring이 자동적으로 트랜잭션을 처리해 주기 때문에 조금 전 입력예제로 사용되었던 소스가 아래처럼 다시 변경될 수 있다.

    getSqlMapClientTemplate().insert("insertMessage", message);
    return true;

    spring의 트랜잭션 관리를 사용하면 위와 같이 소스가 간단해진다.

    이것은 transactionAttributes 속성 하위의 설정값들에 의해 spring의 DI(dependency injection)을 사용하여 가능한 것이지만, 일단 개발자들에게는 SQLMaps로 인해 간단해진 소스가 더욱 심플해졌다는 사실 자체로 행복한 일일 것이다. 이건 개발 프레임워크를 제대로 사용할 때 개발 프레임워크가 개발자에게 주는 혜택이다.

    결과적으로 SQLMaps는

    지금까지의 설명에서 SQLMaps는 기존의 JDBC프로그래밍 방식과 근본적으로 프로그래밍 방식이 바뀌는 건 아님을 알 수 있다. 사실 이런 부분이 기존의 코딩 방식을 그대로 가져가기 때문에 획기적인 개선이 없다는 단점을 낳기도 한다. 개인적으로 SQLMaps는 JDBC프로그래밍 방식과 hibernate와 같은 완전히 다른 방식의 데이터베이스 처리 방식 사이의 중간에 위치한다고 생각한다. 둘의 단점을 모두 가지고 있지만 둘의 장점 또한 모두 가지고 있는 ORM이다. 그 둘의 단점을 피하고 장점만을 제대로 사용한다면 정말 좋은 ORM이라는 건 어느 누구도 의심하지 않을 것이다. 필자는 다음과 같은 경우에 hibernate보다는 SQLMaps가 적합할 것 같다고 생각을 한다.

    • JDBC코딩의 단점은 버리고 싶으나 hibernate와 같은 전혀 다른 방식을 사용하는 것은 부담스러운 프로젝트
    • 기존 JDBC형태의 프로젝트를 ORM 기술을 사용해서 변경하고자 할 때
    • 데이터베이스에 관련된 DBA가 회사 내에 있어서 기존의 SQL에 대한 지식과 경험이 많거나 HQL의 성능이 의심되는 경우

    개발자는 SQLMaps의 설정방법과 맵핑파일에 관련된 몇몇 지식만 가지면 기존의 JDBC방식을 사용하던 개발자가 SQLMaps를 사용하는 건 크게 어렵지 않다. 하지만 JDBC 코드를 SQLMaps로 바꾸었을 때의 결과는 굉장한 긍정적인 차이를 가질 것이라는 점은 위에서 계속 설명했던 바이다

    필자가 설명하는 SQLMaps의 장점이 제대로 전달되었는지는 잘 모르겠다. 사실 이외에도 SQLMaps에서 지원하는 기능은 많다. 물론 여기서 필히 논의가 되었어야 할 dynamic SQL부분이나 로깅관련 사항들은 지면이 모든 내용을 포함하도록 할 수 없는 제한으로 인해 설명되지 못했다. 이 사항들은 관련 문서와 커뮤니티에서 충분한 정보를 얻을 수 있을 것이다. 현재 가장 빠르게 발전하고 있는 ORM은 hibernate임에는 필자도 이견을 달지 않는다. 하지만 오픈소스가 생성된 배경과 의도가 다른 만큼 개발자들이 단순히 기술적인 부분에만 치우쳐 오픈소스를 사용하는 일은 없었으면 한다. 기술적인 부분이 어느 정도 지원하는 수준에서 프로젝트에서 요구하는 상황과 해당 오픈소스의 생성의도가 제대로 맞아떨어질 때 그 오픈소스가 정말 강력한 기능을 발휘할 것이라는 점은 모두가 동의할 것이다. 현재 hibernate는 jboss의 지원을 받고 있고 SQLMaps는 아파치의 지원을 받고 있다. 두 오픈소스가 충분히 발전할 가능성을 가지고 있고 이미 강력한 기능을 지원하는 만큼 적재적소에 해당 오픈소스를 사용하길 바란다.

    참고자료

    iBATIS 홈페이지 - http://incubator.apache.org/ibatis/site/index.html
    SQLMaps 2.0개발자 가이드(한글) http://openframework.or.kr/JSPWiki/attach/Hibernate/iBATIS-SqlMaps-2_ko.pdf
    SQLMaps 2.0튜토리얼(한글) http://openframework.or.kr/JSPWiki/attach/Hibernate/iBATIS-SqlMaps-2-Tutorial_ko.pdf
    SQLMaps를 이용한 객체-관계맵핑 http://openframework.or.kr/JSPWiki/Wiki.jsp?page=ObjectRelationalMappingwithSQLMaps
    네이버 자바프레임워크 http://cafe.naver.com/deve
    네이버 자바프레임워크 위키 http://openframework.or.kr

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:13
    반응형

    ---다이나믹쿼리------------------------------------------

     

     <statement id="UserLikeGenre" resultClass="common.bean.Genre">
      SELECT * FROM GENRE
      <dynamic prepend="WHERE">
       <isNotEmpty prepend="OR" property="genrename1">
        GENRENAME LIKE '%$genrename1$%'
       </isNotEmpty>
       <isNotEmpty prepend="OR" property="genrename2">
        GENRENAME LIKE '%$genrename2$%'
       </isNotEmpty>
       <isNotEmpty prepend="OR" property="genrename3">
        GENRENAME LIKE '%$genrename3$%'
       </isNotEmpty>
       <isNotEmpty prepend="OR" property="genrename4">
        GENRENAME LIKE '%$genrename4$%'
       </isNotEmpty>
       <isNotEmpty prepend="OR" property="genrename5">
        GENRENAME LIKE '%$genrename5$%'
       </isNotEmpty>
      </dynamic>
     </statement>

     

    값이 비어있지 않다면 생성해준다~

     

    statement 를사용하면 '$$' 로 해야 하며~ %%로 검색하기 위해서

    statement를 사용

     

     

    ---간단한 select 문------------------------------------------

     

    <select id="UserCouponeCheck" resultClass="common.bean.Coupone">
      SELECT * FROM COUPONE WHERE ID=#id# AND COUPONEENDDAY
      <![CDATA[>]]>           <-- 요놈은 xml 검증 무시~하기 위해
      SYSDATE
     </select>

     

     

     

    ---간단한 insert 문------------------------------------------

     

     <insert id="UserInsertGenre">
      INSERT INTO MEM_LIKEGENRE(MEMLIKEGENRENO, ID, GENRECODE)
      VALUES(MEM_LIKEGENRE_SEQ.NEXTVAL,#id#,#likegenreno#)
     </insert>

     

     

    ---간단?한 update 문---------------------------------------

     

     <statement id="UserUpdate">
      UPDATE MEMBER SET
      ID='$id$',NAME='$name$',PASSWORD='$password$',SSN='$ssn$',
      DETAILADDR='$detailaddr$',PHONE='$phone$',EMAIL='$email$',
      BIRTHDAY=TO_DATE('$birthday$','yy/mm/dd'),
      MILEAGE='$mileage$',SEQ='$seq$' WHERE ID LIKE '%$id$%' AND
      PASSWORD LIKE '%$password$%' AND ssn LIKE '%$ssn$%'
     </statement>

     

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:12
    반응형

    - iBATIS가 적합하지 않은 경우 ( 정통 ORM 프레임웍이 더 적합한 경우)


     
    1.
    개발자가 데이터베이스에 대한 전권을 가지고 있는 경우.
        개발 완료 후 운영시점에는 데이터베이스에 대한 권한을 가지지 못할 가능성이 있는 경우는 제외.

     2. 개발팀내에 데이터베이스 쿼리에 대한 구루 개발자가 없는 경우

     3. 개발팀내의 개발자들이 새로운 툴 또는 프레임웍에 대한 도전의식이 넘치는 경우 혹은 새로운
        기술에 대한 오픈 마인드를 가지고 있는 경우

     4. 한번의 데이터 액세스 구문 작성으로 여러 데이터베이스를 지원해야 할 경우

     5. 어플리케이션의 전체 레이어가 모두 객체지향적 아키텍쳐를 지향하고 싶은 경우

     6. 데이터베이스의 정규화가 잘 적용되어 있는 경우
     

     

    - iBATIS가 더 적합한 경우 ( 정통 ORM 프레임웍이 적합하지 않은 경우)


     
    1.
    데이터베이스에 대한 전권을 가지고 있지 못한 경우

     2. SQL 쿼리에 대한 완벽한 제어를 해야 하거나 하고 싶은 경우

     3. DBA와 사이가 좋지 않은 경우 혹은 DBA가 직접 쿼리작성을 원하는 경우

     4. 개발팀원이 정통 ORM 툴에 대해 사전 지식이 없거나 학습할 수 있는 기간이 불충분한 경우

     5. 프로시져처럼 SQL 쿼리 구문만을 별도의 공간에 보관하고 싶은 경우

     6. 반복적인 쿼리 작성을 피하고 싶거나, 쿼리 구문의 재활용이 필요한 경우
     7. 데이타베이스의 정규화가 미비한 경우 (물론 잘 정규화된 DB에 대해서는 말할 것도 없고.. ㅡ.ㅡ)
     8. 이미 존재하는 데이터베이스에 대해서 새로운 어플리케이션을 개발해야 하는 경우

    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:08
    반응형

    가장 간단히 설명하면, JAVA에서 DB관련 작업을 편하게 해주는 프레임웍정도라고 할까?

    iBATIS in action에서 iBATIS는 "SQL 실행 결과를 자바빈즈 혹은 Map 객체에 매핑해주는 퍼시스턴스 솔루션으로 SQL을 소스 코드가 아닌 XML로 따로 분리해 관리하여 지겨운 SQL 문자열 더하기에서 해방시켜 줍니다. 또한 XML에서 동적 SQL 요소를 사용하여 쿼리 문장을 프로그래밍 코딩 없이 자유롭게 변환할 수 있게 해줍니다. 이러한 접근방식으로 인해 iBATIS를 사용하면 JDBC를 사용할 때보다 약 60% 정도의 코드만으로 프로그램 작성이 가능하다" 라고 한다.

    말로만 하면 뭔소리인지 모르겠으니 간단한 예제 정도를 들어보자.

    - 일반적인 JDBC 예제
    import javax.naming.*;
    import javax.sql.*;
    import java.sql.*;

    public class Employee {
      public Account getAccount(int id) throws SQLException, NamingException{
        Account account = null;
        
        String sql = "select * from employee where id= ?";
        
        Connection conn      = null;
        PreparedStatement ps = null;
        ResultSet rs       = null;
        
        try {      
          Context ctx = new InitialContext();
          DataSource ds =
                  (DataSource)ctx.lookup(
                     "java:comp/env/jdbc/TestDB"); 
          conn = ds.getConnection();
          ps = conn.prepareStatement(sql);
          ps.setInt(1, id);
          rs = ps.executeQuery();
          
          while( rs.next()){
            account = new Account();
            account.setId(rs.getInt("ID"));        
          }
        } finally {
          try {
            if ( rs != null ) rs.close();
          } finally {
            try {
              if (ps != null) ps.close();
            } finally {
              if (conn != null) ps.close();
            }
          } 
        } 
        return account;  
      }
    }   

    뭐다들 아시겠지만 간단히 쿼리를 날려서 Acount 객체에 담아가지고 오는 소스이다. 대충봐도 무척이나 길다,
    이걸 iBATIS를 이용해서 처리하는 예를 보자, 

    - iBATIS 를 이용한 예
    acount.xml
    <select id="getAcount" resultClass="Acount" parameterClass="java.lang.Integer">

        select * from employee where id= #id#
    </select>

    java
    Acount act = (Acount) sqlMap.queryForObject("getAcount",new Integer(5));
     
    보면 알겠지만 상단에 쿼리를 닮고있는 xml과 아래 간단히 크 쿼리를 실행시키는 java 한줄정도?이다.
    사실 iBATIS를 설정하는 config파일과 sqlMap객체를 불러오는 부분이 있긴하지만, 무척이나 좋아보이도록,
    이것만 쓰겠다. -_-;;

    iBATIS 의 목표와 특징은 몇마디로 짧게정의하다면,

    쉽고, 간단하고, 의존성이 적은 프레임웍이라는 것이다. 
    sql문과 java코드와의 분리만으로도 java개발자는 쿼리문을 신경쓰지 않아도 된다. sql문이 변경되더라도,
    파라미터 값만 변경되지 않는다면, java소스에서는 수정할 부분이 없다.

    ~ 이론적인 면은 대충 접어두고 실전으로 넘어가자(사실 나도잘몰라서;;ㅈㅅ) 

    다음 포스트는 실제로 이클립스에서 오라클 디비와 연동하겠습니다.

    beans.tistory.com
    Posted by 1010
    54.iBATIS, MyBatis/iBatis2008. 11. 13. 10:08
    반응형

    1. 우선 iBATIS 를 다운받습니다.

    2. 다운을 풀고, /lib 폴더에 ibatis-2.3.4.726 를 톰캣의 lib폴더나 프로젝트의 web-inf/lib 폴더에 넣습니다.
    - /현제프로젝트/WebContent/WEB-INF/lib/
    - /톰캣/lib/   (톰캣6버전)

    두폴더중 편한곳에다가 jar파일을 저장합니다.


    3. example 폴더를 타고 들어가보면 sqlMapConfi.xml 파일이 있습니다. 이파일을 복사해서 붙여넣기 하셔도되고
    src폴더에서 새로 xml 파일을 만드셔도 됩니다.

    sqlMapClient.xml

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE sqlMapConfig      
        PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"      
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

    <sqlMapConfig>

      <!-- Configure a built-in transaction manager.  If you're using an 
           app server, you probably want to use its transaction manager 
           and a managed datasource -->
      <transactionManager type="JDBC" commitRequired="false">
        <dataSource type="SIMPLE">
          <property name="JDBC.Driver" value="org.hsqldb.jdbcDriver"/>
          <property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@192.168.10.103:1521:db"/>
          <property name="JDBC.Username" value="ahm"/>
          <property name="JDBC.Password" value="ahm"/>
        </dataSource>
      </transactionManager>

      <!-- List the SQL Map XML files. They can be loaded from the 
           classpath, as they are here (com.domain.data...) -->
      <sqlMap resource="db/Account.xml"/>
      <!-- List more here...
      <sqlMap resource="com/mydomain/data/Order.xml"/>
      <sqlMap resource="com/mydomain/data/Documents.xml"/>
      -->

    </sqlMapConfig>

    빨간부분으로 표시된부분이 제가 수정한 부분입니다. db정보는 propertie로 빼서 관리하는방법도 있으나, 
    우선은 이렇게 하도록 하겠습니다. 

    4. 자바빈즈를 생성합니다. 

    db라는 패키지를 만들고 그 밑에 Acount.java 파일을 생성합니다. 결과를 담아올 빈즈입니다. 
    Account.java

    package
     db;

    public class Account {
      private int id;

      public int getId() {
        return id;
      }

      public void setId(int id) {
        this.id = id;
      }
    }

    5. XML을 생성합니다.

    우리가 사용할 쿼리를 작성하는 XML입니다.
    Account.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap      
        PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
        "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <sqlMap namespace="Account">
      <!-- Select with no parameters using the result map for Account class. -->
      <select id="getAcount" resultClass="db.Acount">  다음값을 이용하여 쿼리와 맵핑합니다.
        select id from ACCOUNT where name=#value#
      </select>
    </sqlMap>

    6. 이제 쿼리를 실행할 JAVA를 작성한다.

    SimpleExample.java

    package db;

    import com.ibatis.sqlmap.client.SqlMapClient;
    import com.ibatis.sqlmap.client.SqlMapClientBuilder;
    import com.ibatis.common.resources.Resources;

    import java.io.Reader;
    import java.io.IOException;
    import java.sql.SQLException;

    public class SimpleExample {

      private static SqlMapClient sqlMapper;

      static {
        try {
          Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
          sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
          reader.close(); 
        } catch (IOException e) {
          // Fail fast.
          throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
        }
      }

      public static Account getAcount() throws SQLException {
        return (Account)sqlMapper.queryForObject("getAcount","ahm");
        // 이부분에서 쿼리를 실행한다. queryForObject는 한개의 데이터를 가져올떄 사용하는 메소드이다.
      }
      
      public static void main(String[] args){
        
        try {
        Account temp = getAcount();    
        System.out.println(temp.getId());
      } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      }
    }

    물론 이 java파일을 실행하기 전에는 DB에 TABLE과 데이터가 준비되어있어야겠다.

    현제 이클립스내에 폴더구조이다.


    이미지와 같이 , iBATIS 를 설정하는 설정파일인 sqlMapConfig.xml 파일과
                   실제 SQL이 담겨져 있는 Account.xml 파일
                   결과를 담아올 객체인   Account.java 파일
                   이러한 과정을 호출하는 SimpleExample.java 파일
                   그리고 WEB-INF/lib 에 ibatis-**.jar 파일 등을 해당폴더에 넣고 위에 순서대로 따라한다면
                   DB에서 요청사항을 무난히 가져올수 있을것이다. 

    다음엔 좀더 세부적인 설정사항이라던지 자세한 정보를 보여드리겠습니다. 
                      HTTP://BEANS.TISTORY.COM

    Posted by 1010
    90.개발관련문서2008. 11. 13. 10:02
    반응형

    디자인은 최종 사용자와 가장 맞닿아 있는 프로덕트를 완성시키는 요소입니다.

    디자인은 사용자에게 이 웹페이지에서 사용자에게 가장 중요하게 말하고 싶은 것이 무엇인가? 어떻게 하면 사용자가 더욱 편하게 이용할 수 있을까? 를 말하지 않아도 설명해 주고 프로덕트의 가치를 올려 줍니다.

    웹디자인은 웹디자이너 뿐만이 아니라 개발자, 기획자, 심지어는 CEO 조차도 알아야 하는 요소 이며, 제공하자고자 하는 서비스/프로덕트에 대한 공통의 합의를 가져 갈 수 있게 하며, 성공의 필수 요소 입니다.

    아래의 링크에는 다운로드 받을 수 있는 30개 이상의 필수 PDF 문서에 대한 것입니다.

    아래 링크의 원본 포스트 : http://www.positivespaceblog.com/archives/pdf-documents-designer/


    RESOURCES


    YAHOO! Design Pattern Library

    The WordPress Help Sheet

    The Advanced WordPress Help Sheet

    AIGA | Aquent Salary Survey

    AIGA Why Design? Booklet

    Type Classification eBook - Jacob Cass

    WEB DEVELOPMENT & PROGRAMMING

    Getting Real - 37signals (Read Online for Free)

    DotMobi Mobile Web Developer’s Guide

    Accessibility Checklist - Aaron Cannon

    CSS Selectors Cheat Sheet - Cameron Moll

    CSS Support in Email Clients

    Dive Into Accessibility

    PRESENTATIONS

    Design is in the Details - Naz Hamid

    Grids are Good - Khoi Vinh & Mark Boulton

    Destroy the “Web 2.0 Look” - Elliot Jay Stocks

    Print is the New Web - Elliot Jay Stocks

    Creating Content for the Web - Naz Hamid

    Elegant Web Typography - Jeff Croft

    Entrepreneurs on Rails - Dan Benjamin

    Bulletproof Web Design - Dan Cederholm

    Interface Design Juggling - Dan Cederholm

    FREELANCING & INCOME

    Web Designer’s Success Guide

    Passive Income Guide - Freelance Switch

    Time Management for Creative People - Mark McGuinness

    A Primer in Social Media - SmashLAB

    Contingency Design - 37signals

    Introduction to Good Usability - Peter Pixel

    How to Be Creative - Hugh MacLeod

    PDF COLLECTIONS

    Creative Latitude Business Resources

    Computer Arts Tutorials

    AIGA Design & Business Forms

    Posted by 1010
    91..개발관련프로그램2008. 11. 13. 09:47
    반응형

    인터넷이 발달하고 저장 공간의 비용이 줄어들면서

    웹에서 여러 부가적인 산출물들이 만들어지고 있습니다.

    최근에는 웹에서 OS와 같은 운영체제를 즐길 수 있는

    고스트(http://g.ho.st/)라는 웹어플리케이션이 있습니다.

    풀스크린으로 사용해서 마치 가상의 데스크톱을 연상케 하지만

    실상은 웹브라우저 안에서 돌아가는 프로그램입니다.

    고스트는 'The Global Hosted Operating System'의 약자로 이름이 지어진 웹 OS입니다.

    오픈라즐로(http://www.openlaszlo.org/)기반의 RIA 플랫폼으로 구성되었습니다.

    고스트에 포함된 애플리케이션들을 살펴보면

    오피스들은 조호(http://www.zoho.com/)를 사용하고

    메일은 짐브라(http://www.zimbra.com/)기반으로 자체 개발해서 이용합니다.

    또한 다양한 위젯과 개발자 API를 사용하여 웹에서도 데스크톱을

    사용하는 것만큼의 편의성을 누릴 수 있는 장점이 있어서 좋네요..

    사용자 삽입 이미지


    [
    사용자 삽입 이미지


    사용자 삽입 이미지


    사용자 삽입 이미지
    Posted by 1010