'Java'에 해당되는 글 2건

  1. 2009.11.03 oracle java programming (2)
  2. 2009.10.28 oracle java programming (1)
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
,
1. Oracle 기본적으로 설치시, (관리자) 로그인 방법 - sqlplus

$> su oracle
passwd :

oracle@easy-pc:/$ sqlplus "/as sysdba"

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

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  238530560 bytes
Fixed Size            1299116 bytes
Variable Size          155192660 bytes
Database Buffers       75497472 bytes
Redo Buffers            6541312 bytes
Database mounted.

Database opened.


위에서 보듯이, idle instance에 접속했다고 나오는데, 이는 oracle instance가 시작을 안햇다는 표시이므로, startup으로 실행시켜준다.

2. 오라클과 자바를 같이 배우기 위해서, 오라클에 자바 서버 플랫폼을 설치한다.
(아마 기본적으로 다 설치되리라 생각됨)

SQL> select count(*), status from user_objects
  2  where object_type=
  3  'JAVA CLASS'
  4  group by status
  5  /

  COUNT(*) STATUS
---------- -------
     20137 VALID


라고 했을시, 결과가 다음과 같이 valid 이면 설치가 된 것이고, 만약 아니라면,
%ORACLE_HOME%/javavm/install 에서 스크립트를 수행해주면 된다.

보이듯이, 2만개가 넘는 자바 클래스 객체들이 생성되어있고, 우린 이것을 사용할 수 있다.


3. 데이터베이스 외부로부터 자바 클래스 파일이나 소스 파일을 로드 하려면 loadjava를 사용하면된다.
이는 %ORACLE_HOME%/bin에 있는 스크립트이다.

jiwoong@easy-pc:~/oj$ loadjava
loadjava: Usage: loadjava [-definer] [-encoding encoding] [-force] [-genmissing] [-genmissingjar jar] [-grant grants] [-help] [-nousage] [-noverify] [-oci8] [-order] [-resolve] [-nativecompile] [-resolver resolver] [-schema schema] [-synonym] [-thin] [-tableschema schema] [-user user/password@database] [-verbose] classes..jars..resources..properties... 


이제 클래스 파일을 DB로 로드 해보자.

jiwoong@easy-pc:~/oj$ cat test.java
public class test{
    public static void main(String[] args){
        System.out.println("hello");
    }
    public static void db_run(){
        System.out.println("db_run");
    }

}


$> javac test.java
$> java test
hello
$>


4. 잠시,

1. 오라클 유저는 DBA만이 생성할 수 있다.

    DBA로 접속한다 

manager login
- sqlplus system/manager
- sqlplus "/as sysdba"

2. create tablespace
- CREATE TABLESPACE test_ts DATAFILE '/export/oracle10/oradata/ORA10g/test_ts.dbf' SIZE 10M

3. create user
- CREATE USER test IDENTIFIED BY password DEFAULT TABLESPACE test_ts TEMPORARY TABLESPACE TEMP QUOTA 500K ON test_ts

4. user permission
- GRANT CONNECT TO test
- GRANT CONNECT, RESOURCE TO test
- GRANT CONNECT, DBA TO test
---------------------------------------------------------------------------
비밀번호 변경

ALTER USER SYS
IDENTIFIED BY "password";


- CREATE USER : 뒤에 사용자 이름

 - IDENTIFIED  BY password : 사용자가 데이터베이스에 의해 인증되도록 지정하며, 데이터베이스

                                            유저 로그온시 사용하는 비밀번호

 - DEFAULT TABLESPACE:  사용자 스키마를 위한 기본 테이블 스페이스를 지정

 - TEMPORARY TABLESPACE: 사용자의 임시 테이블 스페이스를 지정

 - QUOTA절을 사용하여 사용자가 사용할 테이블 스페이스의 영역을 할당


5. jiwoong@easy-pc:~/oj$ loadjava -user jiwoong/jiwoong -resolve -verbose test.class
arguments: '-user' 'jiwoong/***' '-resolve' '-verbose' 'test.class'
creating : class test
loading  : class test
created  : CREATE$JAVA$LOB$TABLE
resolving: class test
errors   : class test
    ORA-29552: ¿¿ ¿¿: java.lang.UnsupportedClassVersionError: test (Unsupported major.minor version 50.0)

Classes Loaded: 1
Resources Loaded: 0
Sources Loaded: 0
Published Interfaces: 0
Classes generated: 0
Classes skipped: 0
Synonyms Created: 0
Errors: 0
jiwoong@easy-pc:~/oj$


중간 에러는 언어땜시??

여튼 클래스를 로딩 완료한듯.



SQL>
  1  select dbms_java.longname(object_name), object_type, status
  2  from user_objects
  3 where object_type like 'JAVA%'

DBMS_JAVA.LONGNAME(OBJECT_NAME)     OBJECT_TYPE        STATUS
------------------- -------
test JAVA CLASS        VALID


보면 test라는 object가 생겼다.

SQL> create or replace procedure run_hello
  2  as language java
  3  name 'test.db_run()';
  4  /

Procedure created.

프로시저를 만들고,


SQL> set serveroutput on size 5000
SQL> call dbms_java.set_output(5000);

Call completed.

dbms_java.set_output을 사용하여 system.out을 SQL*Plus세션으로 출력 방향을 바꾼다... 고 한다.


SQL> execute run_hello;
BEGIN run_hello; END;

*
ERROR at line 1:
ORA-29516: Aurora assertion failure: Assertion failure at eox.c:332
Uncaught exception System error:   java/lang/UnsupportedClassVersionError
ORA-06512: at "JIWOONG.RUN_HELLO", line 1
ORA-06512: at line 1


SQL>

이제 실행을 한 것인데.. 이런 오류가 난다.. 찾아본 결과, java 1.4 로 컴파일을 하란다... 제길..

$> javac -source 1.4 test.java

후 , 위에 등록했던 자바 객체를 drop 시키고 다시 등록 한다.
jiwoong@easy-pc:~/oj$ dropjava -user jiwoong/jiwoong -verbose test.class
dropping: class test

jiwoong@easy-pc:~/oj$ loadjava -user jiwoong/jiwoong -verbose test.class
arguments: '-user' 'jiwoong/***' '-verbose' 'test.class'
creating : class test
loading  : class test
Classes Loaded: 1
Resources Loaded: 0
Sources Loaded: 0
Published Interfaces: 0
Classes generated: 0
Classes skipped: 0
Synonyms Created: 0
Errors: 0


이제 다시, 프로시저를 생성.
SQL> create or replace procedure run_hello2
  2  as language java
  3  name 'test.db_run()';
  4  /

Procedure created.


그리고 실행..

SQL> execute run_hello2
db_run

PL/SQL procedure successfully completed.


오우.. 드디어 db_run을 보다.!!!


이외에도 자바 소스를 로딩하는 법과, 여러개의 자바소스/클래스 파일을 로딩하는 법, DB내에서 자바소스를 작성하는 법이 있으나, 시간 관계상 생략..


참고문헌 ; Oracle 9i Java programming

Posted by Gwoong
,