IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  오픈 소스 | Information Management | 자바  >

Google Web Toolkit, Apache Derby, Eclipse를 사용하여 Ajax 애플리케이션 구현하기, Part 2: 신뢰성 있는 백엔드(back end) (한글)

애플리케이션 개발의 토대, Apache Derby

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.


제안 및 의견
피드백

난이도 : 중급

Noel Rappin, Senior Software Engineer, Motorola, Inc.

2007 년 4 월 10 일

Google Web Toolkit, Apache Derby, Eclipse를 사용하여 Ajax 애플리케이션 구현하기 시리즈, 두 번째 글에서는 웹 애플리케이션용 Apache Derby 데이터베이스를 구현하는 방법과 이것을 사용하여 GWT를 구동하는 방법을 설명합니다. 본 시리즈 Part 1에서는, GWT를 소개했고, 이를 사용하여 웹 애플리케이션용 프론트엔드를 만드는 방법을 설명했습니다. 이번 시간에는, 데이터베이스로 백엔드를 설정하고, GWT가 사용할 수 있는 포맷으로 데이터를 변환하는 코드를 설정하는 방법을 설명합니다. 이 글을 끝내면, 환상적인 프론트엔드와 신뢰성 있는 백엔드가 서로 통신할 준비가 됩니다.

이 글에서, 웹 애플리케이션의 백엔드인 데이터베이스를 설치 및 구성하고, 데이터베이스 스키마를 만들고, 여기에 데이터를 채우는데 사용되는 간단한 툴을 소개한다. 여러분이 사용하게 될 데이터베이스는, 원래 Cloudscape ™라는 이름으로 개발되었던 순수한 자바™ 관계형 데이터베이스인 Apache Derby이다. Cloudscape 코드를 IBM®이 인수했고, IBM은 이것의 오픈 소스 버전을 Apache 프로젝트에 제공된다. 이와 같은 프로젝트가 JavaDB라는 이름으로 Sun Microsystems에서도 배포되는데, 모두가 동일한 선상이라고 이해하면 된다.

Ajax 리소스 센터에서는 Ajax 프로그래밍 모델과 관련한 기술자료, 튜토리얼, 포럼, 블로그, wiki, 이벤트, 뉴스 등이 제공된다.

내가 Derby를 선택한 이유는 이름을 세 가지나 갖고 있어서가 아니라, 경량에다가 구성이 쉽기 때문이다. 대부분의 관계형 데이터베이스와는 달리, Derby는 자바 측 서버 코드와 같은 Java Virtual Machine (JVM) 내에서 실행될 수 있다. (원한다면 개별 JVM에서도 실행할 수 있다.) 개발과 전개가 쉽기 때문에 Derby는 중소형 웹 애플리케이션에 알맞은 선택이라 할 수 있다.

시작하기 전에 몇 가지 알아두어야 할 것이 있다. 먼저, 관계형 데이터베이스, JDBC, Structured Query Language (SQL)에 대한 기본적인 지식이 있어야 한다. 두 번째, 이 글에서는 데모를 목적으로 하는 부분도 있으므로 실행 시스템에는 맞지 않을 수도 있다. 이 글에서는 전반적인 문제들을 다루겠지만 성능 튜닝까지는 설명하지 않겠다.

Derby를 얻는 방법

Derby는 Apache DB 프로젝트의 일부로 사용할 수 있다. 이 글을 쓰고 있는 현재, 10.1.3.1 버전까지 나와있다. Eclipse 통합 개발 환경(IDE)에서 작업할 예정이라면, 두 개의 플러그인, derby_core_pluginderby_ui_plugin으로도 충분하며, 그렇지 않을 경우, 여러분의 필요에 맞는 배포판을 사용해도 좋다. 어떤 배포판은 라이브러리 파일로만 되어있고, 또 다른 것은 라이브러리와 문서이고, 어떤 것은 디버그 정보가 있는 라이브러리이고, 때로는 소스 코드만 있는 것도 있다. Derby는 자바 기술에 전적으로 기반하고 있고, JVM version 1.3 또는 이후 버전에서 실행된다. 이 코드 예제는 Java 1.4를 사용한다.

Eclipse 없이 Derby 설정하기

여러분이 Eclipse를 사용하고 있지 않다면, 다운로드 했던 배포판의 압축을 푼다. lib/derby.jar와 lib/derbytools.jar 파일이 classpath 변수에 있는지를 확인한다. 여러분은 이것을 시스템 레벨에서 수행할 수 있는데, 이 경우 환경 변수 DERBY_INSTALL을 Derby가 있는 디렉토리에 설정하는 것이 좋다. (/opt/bin/db-derby-10.1.3.1-bin에 있는 Derby 디렉토리 포함) IDE 또는 런처(launcher) 스크립트 내에서 이를 수행할 수도 있다. client/server 모드와 임베디드 모드에서 Derby를 사용하고 싶다면 lib/derbyclient.jar와 lib/derbynet.jar 역시 classpath에 있어야 한다.

Eclipse에 Derby 설정하기

Eclipse를 사용한다면 개발을 위한 설정이 훨씬 쉬워진다. Eclipse에서 Derby를 설정하는 단계는 다음과 같다.

  1. 두 개의 플러그인 파일의 압축을 푼다. 각각 plugin이라는 상위 디렉토리를 갖고 있다.
  2. 디렉토리의 내용을 Eclipse 플러그인 디렉토리에 복사한다.
  3. Eclipse에서 프로젝트를 연다.
  4. Project > Add Apache Derby Nature를 클릭하여 Derby로 들어간다. 이렇게 하면 네 개의 라이브러리 파일들을 classpath 프로젝트에 추가하고 ij 명령어 프롬프트에 액세스 하게 된다.

그림 1은 Derby Nature를 추가한 후 Derby 메뉴 모습이다.


그림 1. Eclipse Derby 메뉴
Eclipse Derby 메뉴

Eclipse를 사용하더라도 애플리케이션을 전개할 때 사용할 수 있는 JAR 파일이 있어야 한다. 나중에 이 부분에 대해서 상세히 다루겠다.

스키마 디자인

데이터베이스를 사용하기 전에, 데이터베이스에 어떤 것을 저장할 지를 결정해야 한다. Slicr 애플리케이션에 대한 요구 사항들에 대해서는 아직 언급하지 않았으므로, 데이터베이스가 기본 고객 정보와 주문 정보를 저장하는 것으로 하자.

초기 단계에서 데이터베이스를 다룰 때에는 단순함을 유지하고, 데이터베이스 시스템 기능들을 가능한 적게 사용하는 것이다. 초기에 자바 코드에서 추가 프로세싱을 수행하게 되더라도 말이다. 데이터베이스가 대형 서드 파티에 의존하고 있기 때문에, 데이터베이스 결정이 나머지 애플리케이션에 영향을 미치지 않도록 하라. 프로그램과 데이터베이스 간 접촉 포인트를 최소화 하여, 어떤 지점에서 시스템을 수정 할 경우, 이것이 가능해야 한다. 데이터베이스 성능을 향상시키기 위해 특정 시스템을 사용하는 경향이 있는데, 프로젝트의 마지막 순간까지 이러한 최적화를 미뤄두어야 한다.

데이터베이스 디자인은 단순하다. 고객이 주문을 하며, 주문한 내용은 한 개 이상의 피자가 될 것이다. (여기에서, 음식점에서 다른 음식을 팔 경우는 제쳐두기로 하자.) 피자에는 한 개 이상의 토핑이 있고, 피자 반쪽에만 또는 피자 전체에 올라갈 수 있다.

Customer 테이블 만들기

현재로서는, 주문 내역을 확인할 수 있는 고객 정보만 신경 쓰면 된다. (Listing 1)


Listing 1. Customer 테이블
				CREATE TABLE customers (
    id int generated always as identity constraint cust_pk primary key,
    first_name varchar(255),
    last_name varchar(255),
    phone varchar(15),
    address_1 varchar(200),
    address_2 varchar(200),
    city varchar(100),
    state varchar(2),
    zip varchar(10)
)

CREATE 문에는 표준에서 벗어난 SQL 문법이 있으며, 이것은 Derby에서 새로운 행이 생길 때마다 자동으로 증가하는 ID 컬럼을 만든다. 이러한 작동을 정의하는 구문은 다음과 같다.

ID 컬럼에 대한 다른 옵션은 다음과 같다.

The other option for an Identity column would be:

generate by default as identity

차이점은 generate by default로는 컬럼에 고유의 값을 둘 수 있지만, generate always는 그렇지 않다는 점이다. 또한 여러분은 ID 컬럼을 테이블의 기본 키로 정했다.

실제 값으로 연결하지 않고 데이터베이스에 ID를 갖고 있어야 한다. 전화 번호 같은 것을 키로 사용할 수 있다고 팀의 누군가는 말해줄 것이다. 이것 역시 고객을 구분할 수 있기 때문이다. 하지만 그렇게 하지 말라. 결국, 누군가가 전화 번호를 변경한다면, 전체 데이터베이스를 업데이트 해야 할 것이다.

Order 테이블 만들기

Order 테이블(Listing 2)의 경우, 이것을 고객과 데이터로 연결하고 디스카운트를 적용하면 된다. 코드에서 나머지 가격을 계산할 수 있다.


Listing 2. Order 테이블
				CREATE TABLE orders ( 
	id int generated always as identity constraint ord_pk primary key,
    customer_id int constraint cust_foreign_key references customers, 
    order_time timestamp,
    discount float
)

id 기본 키 외에, customer_id 컬럼이 Customer 테이블을 참조하는 외래 키(foreign Key)가 되도록 선언했다. (선언에 외래 키 컬럼을 포함시키지 않았다면, Derby는 여러분이 다른 테이블의 기본 키를 참조하는 것으로 간주한다.) Derby는 이 테이블에 추가된 customer_id가 실제로 시스템에 있는 고객과 매치하는지를 확인할 것이다. 데이터베이스 관리자는 여러분에게 언제나 이를 수행할 것을 요청할 것이지만, 유효성 검사를 할 필요가 없는 경우도 있다. 외래 값을 알거나 그 값에 대해 유효성 검사를 하기 전에, 데이터를 입력해야 할 때가 있다. 또는, 외래 행을 삭제해야 하지만, 테이블의 행은 유지한다. 이 경우, 고객은 삭제하지만, 데이터 수집 프로세스를 위해 고객의 주문을 유지한다. Derby가 이를 수행하도록 할 수 있지만, 다른 데이터베이스 시스템으로 이동할 수 없다.

Toppings 테이블 만들기

마지막 데이터베이스 디자인 문제는 피자와 토핑이다. 토핑의 경우는 매우 간단하다. (Listing 3)


Listing 3. Toppings 테이블
				
CREATE TABLE toppings(
    id int generated always as identity constraint top_pk primary key,
    name varchar(100), 
    price float
)

문제는, 피자와 토핑의 관계를 어떻게 관리하는가이다. 피자는 주문, 크기, 토핑 세트이다. 기존의 데이터베이스는 Pizza 테이블을 만들고, 피자 ID를 토핑 ID로 연결시키는 다대다(many-to-many) 테이블을 만드는 것이다. 이렇게 하면 좋은 프로퍼티들이 생기게 되고, 무엇보다도, 피자에 무한대의 토핑이 가능하다. 하지만, 이 테이블들 간 데이터베이스 관계를 관리하려면 비용이 많이 든다. 무한 토핑이 필요하지 않다면, Pizza 테이블에 여러 토핑 필드를 포함시킬 수 있다. (topping_1, topping_2, 등). 개념상으로는 더 단순하지만, 가장 유명한 토핑을 산출하기 위해 주문 데이터를 마이닝 해야 한다는 것이 약간 어색하다. 승산이 있다고 생각한다면 하나의 토핑 필드를 갖고, 여기에 비트맵이나 연결 스트링으로 채울 수 있다. 하지만 권하고 싶지 않다.

Pizza 테이블 만들기

잠시 생각한 후에, 완전히 기본적인 폼을 사용하기로 결정했다. 피자에 충분한 토핑을 허용하고 싶겠지만, 같은 테이블에 이 모든 것을 놓으면 모양이 흉해진다. 따라서, Listing 4의 코드를 사용해 보자.


Listing 4. Pizza 테이블
				
CREATE TABLE pizzas (
    id int generated always as identity constraint piz_pk primary key,
    order_id int constraint order_foreign_key references orders,
    size int 
)

CREATE TABLE pizza_topping_map (
    id int generated always as identity constraint ptmap_pk primary key,
    pizza_id int constraint pizza_fk references pizzas,
    topping_id int constraint topping_fk references toppings,
    placement int
)

요약하면, 각각 Small, Medium, Large, Extra Large를 나타내는 1, 2, 3, 4가 있다. 토핑 배치는 왼쪽 반, 피자 전체, 오른쪽 반에 각각 -1, 0, 1을 사용한다. 같은 피자에 페퍼로니 토핑이 두 번 나타나게 함으로써, 페퍼로니를 추가할 수 있다.

주: constraint뒤에 나오는 모든 이름들은 데이터베이스에서 고유한 이름이어야 한다. Derby는 실제로 뒤에서 인덱스를 생성하고, 각 인덱스는 고유한 이름을 갖고 있어야 한다.

이것으로 데이터베이스 스키마 디자인을 끝냈다. 이제 데이터베이스로 들어갈 수 있다.

데이터베이스 채우기

이제 스키마가 생겼으므로, 설정하고 초기 데이터를 입력해야 한다. 이러한 설정 작업을 수행하는 독립 프로그램을 만들 것이다. 하지만, 이 방법만 있는 것은 아니다. Derby ij 명령어를 사용하여 SQL 명령어를 직접 입력하거나, 그래픽 SQL 툴을 사용할 수도 있다. 프로그래밍 방식이 Derby를 시작하는 방법과 Derby가 다른 JDBC 데이터베이스와 어떻게 다른지를 더욱 잘 보여준다. 실제로, SQL 스크립트에 SQL 스키마를 유지할 수도 있다.

우선 몇 가지 정적 데이터로 시작한다. Part 1의 Slicr 페이지에 추가했던 피자 토핑 리스트이다. 정적 데이터를 삽입하는 것이기 때문에 대부분 이 방식을 사용한다. 각각의 토핑이 이름과 기본 가격을 갖고 있는 Toppings 테이블을 설정한다. Listing 5의 코드는 그 데이터를 설정하는 코드이다. 이 모든 토핑들이 같은 가격이라고 가정한다.


Listing 5. Derby에 Toppings 테이블 설정하기
				
public class SlicrPopulatr {

    public static final String[] TOPPINGS = new String[] {
        "Anchovy", "Gardineria", "Garlic", 
        "Green Pepper", "Mushrooms", "Olives", 
        "Onions", "Pepperoni", "Pineapple", 
        "Sausage", "Spinach"
    }
    
    public void populateDatabase() throws Exception {
        Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
        Connection con = DriverManager.getConnection(
                "jdbc:derby:slicr;create=true");
        con.setAutoCommit(false);
        Statement s = con.createStatement();
        s.execute("DROP TABLE toppings");
        s.execute("CREATE TABLE toppings(" +
                "id int generated always as identity constraint top_pk primary key, " +
                "name varchar(100), " +
                "price float)");
        //        
        // All the other create table statements from above would go here...
        //
        for (int i = 0; i < TOPPINGS.length; i++) {
            s.execute("insert into toppings values (DEFAULT, '" +
                    TOPPINGS[i] + "', 1.25)");
        }
        con.commit();
        con.close();
        try {
            DriverManager.getConnection("jdbc:derby:;shutdown=true");
        } catch (SQLException ignore) {}
    }    
    
    public static void main(String[] args) throws Exception {
        (new SlicrPopulatr()).populateDatabase();
    }

여러분이 JDBC에 익숙하다면, 대부분의 코드가 익숙할 것이다. 여기에서 두 가지는 Derby의 기능을 갖고 있는데 이 부분을 다루도록 하겠다. Class.forName 이디엄을 사용하여 드라이버 클래스를 로딩하는 것으로 시작한다. 임베디드 버전의 Derby를 사용하기 때문에 이 드라이버의 클래스 이름은 org.apache.derby.jdbc.EmbeddedDriver이다. 그런 다음, 연결 스트링을 만든다. Derby URL의 폼은 다음과 같다.

jdbc:derby:database name;[attr=value]

데이터베이스 이름은 데이터베이스를 참조할 때 사용하는 이름이다. 서버 코드에서 데이터베이스를 다시 열 때 일관성을 유지하는 한 무엇을 선택하든지 상관 없다.

연결이 된 후에 표준 JDBC로 간다. Statement를 만들어서 테이블을 누락 및 재생성 하는 명령을 실행한다. 오염되었다면, 이 프로그램에서 데이터베이스를 리셋할 수 있다. (그렇지 않을 경우, Derby는 이미 존재하는 테이블을 만들려고 할 때 예외를 던진다.) 테이블을 만든 후에, 토핑 어레이에 각 엔트리에 하나의 insert 문을 사용한다.

insert 문의 SQL 코드는 여러분이 예상하지 못했던 한 가지 기능을 갖고 있다. 나는 아이디 컬럼용 플레이스홀더(placeholder)로서 DEFAULT 키워드를 사용했다. Derby는 insert 문의 컬럼 리스트를 지정하지 않았다면 아이디 컬럼의 슬롯에서 이 키워드를 기대한다.

프로그램이 존재하기 전에 "jdbc:derby:;shutdown=true" URL로 연결할 특별한 호출을 한다. 데이터베이스를 지정할 필요가 없다. 이 호출은 Derby 시스템에게 활성화 된 연결을 중단할 것을 명령한다.

이 프로그램을 실행한 후에, derbyDb.라고 하는 애플리케이션의 상위 레벨 디렉토리에 있는 디렉토리를 보게 될 것이다. 이 디렉토리는 Derby가 데이터를 저장하는 바이너리 파일들을 저장한다. 이 파일을 수정해서는 안된다.

GWT용 데이터 준비하기

데이터베이스 스키마가 만들어지고 정적 데이터가 로딩되면, 그 데이터와 클라이언트를 통신시켜야 한다. 결국, 여러분은 클라이언트-서버 커넥션을 통해 데이터를 직렬화 해야 한다. 직렬화를 위해서, 데이터 클래스들은 GWT가 이들을 보고 처리할 수 있는 곳에 있어야 하며, 다시 말해서, 이 클래스는 client 패키지에서 정의되어야 하고 GWT Java-to-JavaScript 컴파일러에 의해 컴파일 될 수 있어야 한다.

직렬화 되는 클라이언트 클래스에 몇 가지 추가적인 제약 사항들이 있다. 이 클래스는 com.google.gwt.user.client.rpc.IsSerializable 인터페이스를 구현해야 하는데, 이것은 마커 인터페이스로서 어떤 메소드도 정의하지 않는다. 더욱이, 이 클래스의 모든 데이터 필드는 직렬화 가능해야 한다. (일반적인 자바 직렬화와 마찬가지로, 이들을 transient로 표시하여, 필드들이 직렬화 되는 것을 방지할 수 있다.)

무엇이 직렬화 가능한 필드를 만드는가? 먼저, 이 필드는 IsSerializable을 실행하는 유형이거나 이것을 수행하는 수퍼클래스(superclass)를 갖는다. 또는, 필드는 기본 유형들 중 하나가 될 수 있고, 여기에는 자바 프리머티브ㅡ 모든 프리머티브 래퍼 클래스, Date, String이 포함된다. 직렬화 가능한 유형의 어레이나 컬렉션 역시 직렬화 가능하다. 하지만, Collection 또는 List를 직렬화 한다면, GWT에서는 여러분이 실제 유형을 지정한 Javadoc 주석을 달아서 컴파일러가 이를 최적화 하도록 한다. Listing 6은 필드용 샘플과 메소드용 샘플 모습이다.


Listing 6. 직렬화 가능한 필드와 메소드
				
/**
 * @gwt.typeArgs <java.lang.Integer>
 */
private List aList; 

/**
 * @gwt.typeArgs <java.lang.Double>
 * @gwt.typeArgs argument <java.lang.String>
 */
public List doSomethingThatReturnsAList(List argument) {
    // Stuff goes here
}

주: 메소드 리스트에 있는 인자는 주석에 있는 이름으로 지정되어야 하며, 리턴 값은 그렇지 않다.

java.sql과 JDBC와 관련 있는 어떤 것도 직렬화 가능한 객체 리스트에서 빠지지 않았다. 결과 세트에서 데이터 객체로 연결하기 위해 무엇을 하든지 간에, 서버 측 코드에서 수행해야 한다.

이 시점에서, Object-Relational Mapping (ORM)을 입력하거나, 관계형 데이터베이스 구조에서 자바 프로그램의 객체 지향 구조로 데이터를 이동한다. 복잡한 자바 시스템의 경우, 이미 존재하는, ORM 시스템(Hibernate 또는 Castor)를 사용하는 것이 좋다. 이러한 두 시스템 모두 데이터베이스에서 자바 객체로 데이터를 자동으로 로딩한다. 하지만, 시작하기 전에 추가 설정이 필요하다. 여기에서는 Derby와 GWT가 중심이므로 개발 시작 시 작동하는 컨버터를 사용한다. 여러분은 이보다 더 강력한 툴을 사용할 수도 있다.

ORM 컨버터

우선, 모든 데이터 테이블을 위해 빈 클래스를 만든다. 나는 예제로 단순하고 데이터를 갖고 있는 Topping 클래스를 사용하기로 한다. 테이블의 각 컬럼에 빈-네이밍 규약을 사용하지만 언더스코어를 Mixed Case로 변환한다. (topping_idgetToppingId가 된다.) Listing 7은 Topping 클래스이다.


Listing 7. Topping 클래스
				
package com.ibm.examples.client;

import com.google.gwt.user.client.rpc.IsSerializable;

public class Topping implements IsSerializable {

    private Integer id;
    private String name;
    private Double price;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Double getPrice() {
        return price;
    }
    public void setPrice(Double price) {
        this.price = price;
    }
}

Listing 8은 단순한 ORM 툴이다.


Listing 8. ORM 툴
				
package com.ibm.examples.server;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class ObjectFactory {

    public static String convertPropertyName(String name) {
        String lowerName = name.toLowerCase();
        String[] pieces = lowerName.split("_");
        if (pieces.length == 1) {
            return lowerName;
        }
        StringBuffer result = new StringBuffer(pieces[0]);
        for (int i = 1; i < pieces.length; i++) {
            result.append(Character.toUpperCase(pieces[i].charAt(0)));
            result.append(pieces[i].substring(1));
        }
        return result.toString();
    }

    public static List convertToObjects(ResultSet rs, Class cl) {
        List result = new ArrayList();
        try {
            int colCount = rs.getMetaData().getColumnCount();
            while (rs.next()) {
                Object item = cl.newInstance();
                for (int i = 1; i <= colCount; i += 1 ) {
                    String colName = rs.getMetaData().getColumnName(i);
                    String propertyName = convertPropertyName(colName);
                    Object value = rs.getObject(i);
                    PropertyDescriptor pd = new PropertyDescriptor(propertyName, cl);
                    Method mt = pd.getWriteMethod();
                    mt.invoke(item, new Object[] {value});
                }
                result.add(item);
            } 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result;
    }
}

convertToObjects() 메소드는 결과 세트를 반복하고, JavaBean 리플렉션을 사용하여 프로퍼티 게터(getter)를 추론하고, 모든 값을 설정한다. convertPropertyName() 메소드는 SQL underscored 네이밍 규약을 자바 mixed-case 규약으로 전환한다.

ORM 툴이 하지 않는 것

ORM 기능이 유용하지만 ORM 툴이 할 수 없는 일도 있다.

  • 같은 객체의 다중 버전을 만들 수도 있다.
  • 데이터베이스에 여러분이 작성할 수 없다.
  • 작업이 느리다.



여러분이 생각하는 것 보다 더 많은 일을 한다. 추가 구성 없이 어떤 데이터베이스 툴에서도 바로 실행할 수 있다. 스키마가 변경될 때 초기 개발 동안 매핑 파일을 데이터베이스와 연결할 필요가 없다. 나중에 보다 강력한 툴로 바꾸기도 쉽다.

Listing 9는 툴의 실행 모습이다. 여러분이 앞서 생성했던 모든 Topping 인스턴스들을 읽는다.


Listing 9. ORM 툴 테스트
				
public class ToppingTestr {

    public static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";

    public static final String PROTOCOL = "jdbc:derby:slicr;";

    public static void main(String[] args) throws Exception {
        try {
            Class.forName(DRIVER).newInstance();
            Connection con = DriverManager.getConnection(PROTOCOL);
            Statement s = con.createStatement();
            ResultSet rs = s.executeQuery("SELECT * FROM toppings");
            List result = ObjectFactory.convertToObjects(rs, Topping.class);
            for (Iterator itr = result.iterator(); itr.hasNext();) {
                Topping t = (Topping) itr.next();
                System.out.println("Topping " + t.getId() + ": " +
                        t.getName() + " is $" + t.getPrice());
            }
        } finally {
            try {
                DriverManager.getConnection("jdbc:derby:;shutdown=true");
            } catch (SQLException ignore) {}
        }
    }

}

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

이 테스트 프로그램은 Slicr 데이터베이스에 대한 Derby 커넥션을 만든다. (프로토콜 스트링에 데이터베이스를 생성할 것을 요청할 필요가 없다.) 단순한 SQL 쿼리를 만든 다음, 결과를 팩토리로 전달한 후, 결과 리스트를 자유롭게 순환(loop)하고 데이터베이스를 종료한다.

다음 편 예고

여러분의 데이터베이스는 이제 설치 및 구성이 완료되었다. 데이터베이스 스키마를 만들었고 데이터를 입력할 간단한 툴에 대해서도 알아보았다. 두 편의 글을 통해서 여러분의 Slicr 프로젝트는 이제 단순하지만 충분한 기능을 수행하는 프론트엔드와 백엔드를 갖추었다. 다음 단계는 통신(communication) 단계이다. 다음 글에서는 Remote Procedure Call (RPC)의 코딩과 관리를 쉽게 하기 위해 GWT가 사용하는 프레임웍을 설명하도록 하겠다.

기사의 원문보기



참고자료

교육

제품 및 기술 얻기

토론


필자소개

Noel Rappin, Ph.D.는 Georgia Institute of Technology의 Graphics, Visualization, Usability Center 소속이며 Motorola의 시니어 소프트 엔지니어이다. wxPython in Action과 Jython Essentials를 공동 집필했다. Noel의 블로그는 10printhello.blogspot.com이다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



아니오잘 모르겠음
 


 


12345
 



위로


Cloudscape, IBM and the IBM logo are registered trademarks of IBM in the United States, other countries or both. Java is a trademark of Sun Microsystems in the United States, other countries, or both. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.

    IBM 소개개인정보 보호정책문의