관리 메뉴

nkdk의 세상

JDBC와 JTA운용 본문

My Programing/EJB

JDBC와 JTA운용

nkdk 2008. 5. 20. 19:34

JDBC와 JTA운용

JTA는 Java Transaction APIs 단일 데이터베이스나 데이터베이스가 여러 개를 이용할 경우 트랜잭션을 제어하기 위한 목적으로 사용한다.

웹로직 서버는 2개 이상의 자원을 이용할 경우 2단계 커밋(2PC, 2Phase Commit)을 제공하는데 이때 JTA를 사용한다.

 

분산 트랜잭션을 사용할 경우 반드시 XA를 준수하는 JDBC 드라이버를 사용해야 한다.

 

Chapter4는 커넥션 풀을 설정하는 내용으로 기존의 클래스패스에서 JDBC 관련한 내용을 모두 지운후 아래를 따라가야 한다.

 

1. XA JDBC를 사용하지 않는 데이터베이스 설정

초기의 JDBC 프로그래밍은 DriverManager 라는 클래스를 이용해서 커넥션을 생성했는데

DriverManager 클래스는 내부적으로 정적인 필드와 메소드를 사용함으로써 쓰레드 상태로 사용하기에는 문제가 있었다.

이러한 문제를 해결하기 위해서 javax.sql.DataSource 객체를 새로 만들게 되었다.

 

커넥션 풀 설정

1.       콘솔화면에서 mydomain -> services ->JDBC ->Connection Pools 항목을 클릭한다.

2.       오른쪽 메뉴에 Configure a New JDBC Connection Pool 링크를 클릭해서 새로운 JDBC 커넥션 풀을 설정한다.

3.       Configure a New Connceion Pool 을 선택한다.

4.       Oracle’s Driver(Thin) Version:8.1.7,9.0.1,9.2.0 드라이버를 선택한 후 Continue를 클릭한다.

5.       커넥션 풀에 대한 설정을 한 후 Continue 클릭한다.

6.       설정이 제대로 되었는지 Test Driver Configuration 을 클릭한다.

7.       커넥션이 성공했다는 메시지를 확인 한 후 Create and Deploy 버튼을 클릭한다.

 

데이터 소스 설정

커넥션 풀에 대한 설정이 끝났다면 데이터 소스에 대한 설정을 해야 한다. 데이터 소스를 이용하는 이유는 데이터베이스의 커넥션을 얻어오는 방법을 간단히 하기 위해서다.

데이터 소스는 JDBC 2.0스펙에서 도입되었으며, 데이터 소스는 커넥션 객체를 위한 팩토리로 사용하는 것이다.

웹로직 서버에서 데이터베이스를 이용한 프로그래밍을 하려면, 커넥션 풀과 데이터 소스를 JNDI 네이밍 서비스로 등록한 후 사용해야 한다.

1.       mydomain -> Service -> JDBC -> DATA Sources 항목을 콘솔 창 좌측 메뉴에서 클릭한 후, 우측 창에서 Configuration a new JDBC Data Source 항목을 클릭한다.

2.       데이터소스명을 OracleDataSource 로 JNDI 저장소에 등록될 이름을 ora9으로 지정한 후 Continue 버튼을 클릭한다.

3.       앞서 설정한 OracleConnectionPool을 선택한 Continue 버튼을 클릭한다.

4.       데이터 소스가 사용될 서버를 선택한 후(기본적으로 선택되어 있다) Create 버튼을 클릭한다.

 

 

 

데이터 소스를 이용한 테스트 예제 작성

테이블의 목록을 보여주는 테스트 파일을 작성해 본다.

 

tablelist.jsp

 

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%@ page import="javax.sql.*" %>

<%@ page import="javax.naming.*" %>

 

<html>

<head>

<title>사용자가 가지고 있는 모든 테이블 보기</title>

</head>

<body>

             <h3>

<%

             Context ctx = null;

             DataSource ds = null;

             Connection con = null;

             Statement stmt = null;

             ResultSet rs = null;

 

             String sql = "select * from tab";

 

             try {

                          ctx = new InitialContext();

                          ds = (javax.sql.DataSource)ctx.lookup("ora9");

                          con = ds.getConnection();

                          con.setAutoCommit(false);

                          stmt = con.createStatement();

                          rs = stmt.executeQuery(sql);

                          while(rs.next()) {

                                       out.println(rs.getString(1) + "&nbsp;&nbsp;&nbsp;" + rs.getString(2));

                          }

             } catch(Exception e){

                          out.println(e.toString());

             } finally {

                          if(rs!=null){

                                       try {

                                                    rs.close();

                                       }catch(SQLException ex){}

                          }if(stmt!=null){

                                       try{

                                                    stmt.close();

                                       }catch(SQLException ex){}

                          }if(con!=null){

                                       try{

                                                    con.close();

                                       }catch(SQLException ex){}

                          }

             }

%>

             </h3>

</body>

</html>

 

위 소스를 webtest 디렉토리에 저장한 후 테스트 해 본다.

에러의 대부분은 커넥션 풀 설정에서 잘못된 값을 저장한 경우이다.

만약 JDBC 드라이버를 Xa를 지원하는 드라이버로 잘못 지정한 경우는 다음과 같은 에러가 발생한다.

java.sql.SQLException:

SQL operations are not allowed with no global transaction by default for XA drivers.

If the XA driver supports performing SQL operations with no global transaction,

explicitly allow it by setting "SupportsLocalTransaction" JDBC connection pool property to true.

In this case, also remember to complete the local transaction before using the connection again

for global transaction, else a XAER_OUTSIDE XAException may result.

To complete a local transaction, you can either set auto commit to true or call

Connection.commit() or Connection.rollback().

 

위와 같은 에러가 나면 커넥션 풀 설정을 삭제하고 다시 설정하고 테스트한다.

 

2. XA을 지원하는 데이터베이스 프로그래밍을 위한 설정

 

XA JDBC 드라이버를 이용하는 이유는 JTA를 이용하기 위해서다.

JTA를 이용할 경우의 장점은 데이터베이스를 2개 이상 사용하거나, 자원 두 개 이상을 이용할 때, XA 스펙을 지원하는 자원일 경우 2단계 커밋을 지원함으로써 좀더 안정적인 트랜잭션을 처리할 수 있기 때문이다.

마찬가지로 XA JDBC 드라이버를 이용해도 커넥션 풀과 데이터 소스를 지정해야 한다

 

커넥션 풀과 데이터 소스 지정

1.       콘솔 화면에서 mydomain->services -> JDBC ->Connection Pools 항목을 마우스 커서를 올려놓은 후 우측 버튼을 클릭해서 Configure a New JDBCConneciotnPool 항목을 클릭한다.

2.       데이터베이스 형식은 Oracle , 데이터베이스 드라이버는 Oracle’s Driver(Thin XA) Version:8.1.7,9.0.1,9.0.2을 선택한 후 Continue 버튼을 클릭한다.

3.       커넥션 풀 속성을 지정한다. 커넥션 풀 이름을 OracleXAConnectionPool 로 설정한다.

4.       Test Driver Configuration 버튼을 클릭한다.

5.       성공 메시지가 나오면 Create and Deploy 버튼을 클릭한다.

 

데이터 소스 생성

해당 커넥션 풀을 이용하는 데이터 소스를 생성해야 한다.

1.       콘솔화면에서 mydomain->services->JDBC->Data Sources 항목에 마우스 커서를 올려놓은 후 오른쪽 버튼을 눌러서 Configuration a new JDBCTxDataSource 를 클릭한다.

2.       데이터소스에 대한 이름을 OracleXADataSource 로, JNDI이름을 oraxa9로 설정한다.

3.       커넥션 풀을 선택한다. OracleXAConnectionPool를 선택한다.

4.       데이터소스가 사용될 서버를 선택한 후 Create 버튼을 클릭한다.

 

XA 데이터 소스를 이용한 테스트 예제 작성

tablelist.jsp 파일을 다음과 같이 고친다.

 

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%@ page import="javax.sql.*" %>

<%@ page import="javax.naming.*" %>

<%@ page import="javax.transaction.*" %>

 

<html>

<head>

<title>사용자가 가지고 있는 모든 테이블 보기</title>

</head>

<body>

             <h3>

<%

             Context ctx = null;

             DataSource ds = null;

             Connection con = null;

             Statement stmt = null;

             ResultSet rs = null;

           UserTransaction tx = null;

 

             String sql = "select * from tab";

 

             try {

                          ctx = new InitialContext();

                      tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");

                      tx.begin();

                          ds = (javax.sql.DataSource)ctx.lookup("oraxa9");

                          con = ds.getConnection();

                          con.setAutoCommit(false);

                          stmt = con.createStatement();

                          rs = stmt.executeQuery(sql);

                          while(rs.next()) {

                                       out.println(rs.getString(1) + "&nbsp;&nbsp;&nbsp;" + rs.getString(2));

                          }

                      tx.commit();

             } catch(Exception e){

                          out.println(e.toString());

             } finally {

                          if(rs!=null){

                                       try {

                                                    rs.close();

                                       }catch(SQLException ex){}

                          }if(stmt!=null){

                                       try{

                                                    stmt.close();

                                       }catch(SQLException ex){}

                          }if(con!=null){

                                       try{

                                                    con.close();

                                       }catch(SQLException ex){}

                          }

             }

%>

             </h3>

</body>

</html>

 

 

XA 드라이버를 이용할 경우 UserTransaction에 포함된 begin(), commit(), rollback() 메소드를 이용해서 두 개 이상의 데이터베이스나 자원에 대해서 트랜잭션을 처리 할 수 있게 된다.

데이텃 소스를 얻기 전에 다음과 같이 UserTransaction을 JNDI를 통해서 얻어온 후 시작한다