JDBC를 통한 오라클 접속

1. 드라이버 유형
유형 1. JDBC-ODBC 브리지
  JDBC와 ODBC를 연결해서 데이터베이스에 접근할 수 있는 기능을 제공
유형2. Native API-부분 자바 드라이버
  자바에서 C/C++ 과 같은 다른 언어들에 내장된 DB에 접근하기 위한 네이티브 API를 호출 할 수 있도록 해준다.
유형 3. JDBC-Net 순수 자바 드라이버
  JDBC호출을 DBMS 에 독립적인 네트워크 프로토콜로 변환시킨다.
유형 4. 네이티브 프롴토콜 - 순수 자바 드라이버
  100%순수 자바 드라이버.


2. 간단한 JDBC 애플리케이션
DBConnection 클래스의 논리적인 흐름
JDBC클래스 import -> JDBC드라이버 등록 -> 접속 생성 -> 생성 문장 -> 문장 실행 -> 결과 처리 -> 리소스 달기


다음은 JDBC를 이용하여 orcle db에 연결하는 간단한 소스.

import java.sql.*;

public class DBConn{
    public static void main(String args[]){
        if(args.length<3){
            System.out.println("Syntax Error : DBConn [url] [user] [pass]");
            System.exit(-1);
        }
       
        String url=args[0];
        String username=args[1];
        String password=args[2];
       
        String sql="select object_name, object_type from user_objects";
        String objName, objType;
       
       
        try{
            System.out.println("Step01. Registering JDBC Driver");
            DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
           
            System.out.println("Step02. Establishing conn to :"+url);
            Connection con=DriverManager.getConnection(url,username,password);
            System.out.println("---->> Connected to oracle");
           
            System.out.println("Step03. Creating SQL statement");
            Statement st=con.createStatement();
           
            System.out.println("Step04. executing SQL");
            ResultSet rs=st.executeQuery(sql);
           
            System.out.println("Step05. Printing results");
            while(rs.next()){
                objName=rs.getString("object_name");
                objType=rs.getString("object_type");
               
                System.out.println("     *"+objType+" " +objName);
            }
           
            System.out.println("Step06. Closing JDBC objects");
            rs.close();
            st.close();
            con.close();
        }catch(SQLException e){
            System.out.println("The folowing error : "+e);
        }
       
       
    }


소스는 주석을 달지 않아도 될 정도로 간단하다.

그러나, 실행하는데 있어서 대여섯개의 에러를 만났다 -_-;;

오류 유형 1. Exception in thread "main" java.lang.NoClassDefFoundError: oracle/jdbc/OracleDriver

CLASSPATH에 jdbc의 library를 미추가 한 경우이다.

$ORACLE_HOME/jdbc/lib/ 에는 4개의 jar 파일이 있는데, (11g 기준)
이들을 CLASSPATH에 설정해주어야 한다.

자신의 계정의 dir에 보면 .profile이 있다.
이를 열어서,
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/ojdbc5.jar:$ORACLE_HOME/jdbc/lib/ojdbc6.jar를 써주고, 또,
export LD_LIBRARY_PATH=$ORACLE_HOME/jdbc/lib 라고 추가로 써준다.
($ORACLE_HOME 이라는 변수가 이미 설정되어 있어야 함은 물론이다. 또한 이보다 더 자세한 정보는
$ORACLE_HOME/jdbc/ 안에 Readme.txt 파일이 친절하게 들어있다.)

위에 .profile에 설정을 했다면, 당장 바로 그 설정이 적용되는 것이 아니다. (재부팅 시 적용)
그러므로 source .profile 이라는 명령어로 당장 설정 파일을 적용한다. (.profile 이 있는 경로에 있다 치자)

이렇게 설정을 하고선 다시 javac DBConn.java 를 하면.. 컴파일이 깔끔하게 된다!!
(아니면 임시방편으로 컴파일할때만 lib 를 추가할 수도 있다. ==> javac -classpath $ORACLE_HOME/jdbc/lib/ojdbc5.jar DBConn.java )

오류 유형2. java.sql.SQLException: No suitable driver found for jdbc
위처럼 컴파일을 끝내고 나서 DBConn 을 실행하는데, 다음과 같이 실행한다.

$> java DBConn jdbc:oracle:thin:@localhost:1521:orcl username password

여기서 jdbc:oracle 부분은 같고, thin 이라는 것은 jdbc 의 타입인데, 자세한것은 검색하자. (oci 유형이 있다고 나와있다)
@localhost 부분은 db 서버의 이름을 써주고, 1521은 포트 번호이다. (설치시 건드리지 않았다면 디폴트로 1521이므로 그대로 적는다)
orcl은 SID라고 해서 오라클 인스턴스의 이름이다. 이 역시 설치시 기본으로 orcl이라는 인스턴스가 생성이 되니 적는다. (orcl 말고 다른 인스턴스가 있다면 그 인스턴스를 적는다)

(만약 내가 어떤것인지 정확히 모르겠다면,
$ORACLE_HOME/network/admin/tnsnames.ora 파일을 보면,
HOST =  이부분이 localhost 와 매치되고,
PORT = 이부분이 1521과 매치되고,
SERVICE_NAME= 이부분이 orcl 과 매치된다. )

자 이제 username과 password를 넣고 (sysdba계정도 되고, 자신이 직접 추가한 게정도 된다. )
수행을 한다...

java DBConn jdbc:orcale:thin:@localhost:1521:orcl jiwoong jiwoong
Step01. Registering JDBC Driver
Step02. Establishing conn to :jdbc:orcale:thin:@localhost:1521:orcl
The folowing error : java.sql.SQLException: No suitable driver found for jdbc:orcale:thin:@localhost:1521:orcl

다음과 같은 오류가 나왔다....쉽게 되는법이 없어 -_-;;
이 오류는 역시 위와 비슷하게 jdbc를 위한 적절한 드라이버가 없다는 내용인데.. 검색을 해보면
classpath 이야기 뿐이다.. 뭐지??

jiwoong@easy-pc:/oracle/11g/network/admin$ source ~/.profile

jiwoong@easy-pc:/oracle/11g/network/admin$ env|grep PATH
LD_LIBRARY_PATH=/oracle/11g/jdbc/lib
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/jiwoong/java/bin:/oracle/11g/bin:/home/jiwoong/java/bin:/oracle/11g/bin:/home/jiwoong/java/bin:/oracle/11g/bin:/home/jiwoong/java/bin:/oracle/11g/bin
CLASSPATH=.:/home/jiwoong/java/jre/lib/ext:/home/jiwoong/java/lib/tools.jar:/oracle/11g/jdbc/lib/ojdbc5.jar:/oracle/11g/jdbc/lib/ojdbc6.jar

이것은 내 환경 설정인데, classpath에 보면 ojdbc5와 ojdbc6가 잘 등록 되어있다... 그런데도 왜 안되지??
한참 생각하다가 문득 떠오르는게 있었다.

아까전에 $ORACLE_HOME/jdbc/에 Readme.txt 를 읽었었는데, jdk 1.5를 쓴다면 ojdbc5를 등록하고, jdk1.6을 쓴다면 ojdbc6을 등록하라 했던거 같은데.. 내가 현재 jdk1.6을 설치했으니.. javac 로 컴파일을 아무옵션 주지 않고 했다면.. 분명 1.6 버전으로 컴파일이 되었을 건데,
위의 classpath에는 1.5버전을 위한 jdbc가 먼저 등록이 되어있기 때문에 충돌이 난게 아닐까.. 라는생각..

부랴부랴 javac -source 1.5 DBConn.java 로 컴파일을 하고,
다시 , java DBConn ~~~ 를 해주었다...


오류 유형 3. The Network Adapter could not establish the connection

jiwoong@easy-pc:~/workspace/DBConn/src$ javac -source 1.5 DBConn.java
jiwoong@easy-pc:~/workspace/DBConn/src$ java DBConn jdbc:oracle:thin:@localhost:1521 jiwoong jiwoong
Step01. Registering JDBC Driver
Step02. Establishing conn to :jdbc:oracle:thin:@localhost:1521
The folowing error : java.sql.SQLException: IO 예외 상황: The Network Adapter could not establish the connection

아 역시... 해결은 되었지만 또다른 문제 -_-;;
역시 일단 검색을 했더니, 다양한 해결책들이 있었다..
책에는 jdbc 드라이버가 host나 리스너 포트를 인식하지 못해서 나온다고 한다..
ping localhost 를 하면 정상 확인이 되고,
리스너 포트를 확인하라길래, telnet localhost 1521로 했다가 안열려서 포트를 열어야 하나 했다..

그러다가 tnsping 이라는 리스너를 확인하는 oracle 프로그램을 알게 되었고,

jiwoong@easy-pc:~/workspace/DBConn/src$ tnsping localhost

TNS Ping Utility for Linux: Version 11.1.0.6.0 - Production on 03-NOV-2009 23:08:20

Copyright (c) 1997, 2007, Oracle.  All rights reserved.

Used parameter files:
/oracle/11g/network/admin/sqlnet.ora

Used EZCONNECT adapter to resolve the alias
Attempting to contact (DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
TNS-12541: TNS:no listener

마지막 라인에 보면 TNS : no listener 이라고 나와있다.. 이게 문제였던듯..

이제 리스너를 실행하기 위해서,

jiwoong@easy-pc:~/workspace/DBConn/src$ lsnrctl start

LSNRCTL for Linux: Version 11.1.0.6.0 - Production on 03-NOV-2009 23:09:20

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Starting /oracle/11g/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 11.1.0.6.0 - Production
System parameter file is /oracle/11g/network/admin/listener.ora
Log messages written to /oracle/diag/tnslsnr/easy-pc/listener/alert/log.xml
Error listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
TNS-12555: TNS:permission denied
 TNS-12560: TNS:protocol adapter error
  TNS-00525: Insufficient privilege for operation
   Linux Error: 1: Operation not permitted

이런.. 퍼미션 에러다..

오라클 접속 유저인 oracle로 접속해서 다시 리스너를 실행시켰다.

oracle@easy-pc:/home/jiwoong/workspace/DBConn/src$ lsnrctl start

LSNRCTL for Linux: Version 11.1.0.6.0 - Production on 03-NOV-2009 23:10:36

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Starting /oracle/11g/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 11.1.0.6.0 - Production
System parameter file is /oracle/11g/network/admin/listener.ora
Log messages written to /oracle/diag/tnslsnr/easy-pc/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=easy-pc)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.1.0.6.0 - Production
Start Date                03-NOV-2009 23:10:38
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /oracle/11g/network/admin/listener.ora
Listener Log File         /oracle/diag/tnslsnr/easy-pc/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=easy-pc)(PORT=1521)))
The listener supports no services
The command completed successfully


위에 보면 리스너가 성공적으로 수행된것을 확인할수 있다.

이제 다시 tnsping ..


oracle@easy-pc:/home/jiwoong/workspace/DBConn/src$ tnsping localhost

TNS Ping Utility for Linux: Version 11.1.0.6.0 - Production on 03-NOV-2009 23:10:47

Copyright (c) 1997, 2007, Oracle.  All rights reserved.

Used parameter files:
/oracle/11g/network/admin/sqlnet.ora

Used EZCONNECT adapter to resolve the alias
Attempting to contact (DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
OK (10 msec)

오우... 드디어 리스너가 먹혔다...

에러유형 4. Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor

jiwoong@easy-pc:~/workspace/DBConn/src$ java DBConn jdbc:oracle:thin:@localhost:1521:orcl jiwoong jiwoong
Step01. Registering JDBC Driver
Step02. Establishing conn to :jdbc:oracle:thin:@localhost:1521:orcl
The folowing error : java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
localhost:1521:orcl

아후.. 또 오류...
중간에 보면 SID라는 말이 나오자마자, 조금 본게 있어가지고 export SID=orcl을 해주고,
수행을 다시 했다..

jiwoong@easy-pc:~/workspace/DBConn/src$ export SID=orcl
jiwoong@easy-pc:~/workspace/DBConn/src$ java DBConn jdbc:oracle:thin:@localhost:1521:orcl jiwoong jiwoong
Step01. Registering JDBC Driver
Step02. Establishing conn to :jdbc:oracle:thin:@localhost:1521:orcl
---->> Connected to oracle
Step03. Creating SQL statement
Step04. executing SQL
Step05. Printing results
     *INDEX SYS_C009648
     *TABLE CREATE$JAVA$LOB$TABLE
     *LOB SYS_LOB0000070938C00002$$
     *JAVA CLASS test
     *PROCEDURE RUN_HELLO
     *PROCEDURE RUN_HELLO2
Step06. Closing JDBC objects


성공............ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

간단한 접속을 하기 위해서 -_-;두시간 이나 삽질했당...


으흐흐.. 참고책은 Oracle 9i Java Programming (정보문화사)
Posted by Gwoong
,