** 본 요약은 한빛미디어 '하이버네이트 프로그래밍' 책을 기준으로 작성되어져 있다.

** 본 설명은 바로 따라하기 하기엔 어려움이 있다. 책을 보지 않은 사람에게는 간단히 어떤 기능을 제공하는지 이해하는데 목적을 둔다.

** 하이버네이트 3.2.5.ga 버전, Ant 빌드를 기본적으로 사용한다.


7장 설정 파일 대신 어노테이션 사용하기

이전 장에서는 XML 매핑 문서를 기준으로 책의 내용을 진행해왔습니다. 이번 장에서는 자바 어노테이션을 이용해 어떻게 매핑 문서를 대체하는지 설명합니다.


하이버 네이트의 철학 : 오래된 어떤 자바 객체라도 어떤 방법으로든 영속화 한다.


자바의 어노테이션(Annotation) 


자바에서 보통의 클래스나 필드, 혹은 메소드에 부가적인 정보를 추가하는 문법이다. JAVA 5 버전부터 정식으로 지원하게 되었으며, 이전에는 JavaDoc의 형태를 이용해 작성하여 사용하였었다. JavaDoc는 프로그래머가 소스 코드에서 개별 파일로 분리해 별도로 관리하지 않으면서도 클래스나 API등의 수준 높은 만드는데 사용하는 방법이다. JavaDoc를 기존 목적 이외의 기능에 사용하려고 하였으며, 이를 활용해 XDoclet 프로젝트를 만들었습니다. 물론 하이버네이트에서는 이 프로젝트를 이용해 하이버네이트 XDoclet 태그도 개발되었습니다.

 


하이버네이트 어노테이션


어노테이션을 사용한 방법은 객체와 매핑 명세 정보를 한 파일에서 관리할 수 있도록 해, 파일을 읽는 사람은 무슨 일을 처리하는 내용인지 좀 더 쉽게 이해 할 수 있습니다. 또한 프로그래머는 설정에 필요한 작업량을 줄일 수 있는 장점이 있습니다.


하지만 객체 모델을 다양한 데이터베이스에 맞춰 변경해야 한다면 어노테이션 사용법은 적합하지가 않습니다. 이럴 경우에는 여러 개의 분리된 매핑 파일 세트를 만들어 사용하는 것이 더 적합합니다. 


그러면 하이버네이트 어노테이션을 사용하기 위해 다음과 같은 작업이 필요합니다. 


1. Hibernate annotations 라이브러리 다운로드 (3.2.5.ga 버전 기준)

-> 3.5 버전부터는 Hibernate core로 통합됨

2. annotation을 이용한 자바 객체 생성하기 

3. hibernate.cfg.xml 파일내 맵핑 파일 대신 맵핑 클래스 추가하기

-> JPA 인터페이스에 의존하는 스타일로 완전히 전환하면 맵핑 클래스 추가 없이 하이버네이트에서 자동으로 클래스를 찾아 낼 수 있다.(하이버네이트 세션 대신 JPA EntityManager의 하이버네이트 구현을 사용해야 한다)

4. 스키마 생성시 <annotationconfiguration> 태그 사용하기

-> Hibernate tool을 이용해 스키마 생성시 자바 객체 클래스들은 미리 컴파일 되어 있어야만 한다.

5. 하이버네이트 이용을 위해 config 정보를 읽는 클래스를 Configuration 대신 AnnotatoinConfiguration 클래스로 변경하기


어노테이션을 이용한 자바 객체 작성 방법


다음 소스를 보면서 자바 객체 작성법을 import 부분, class 부분, 그리고 attribute(속성) 부분으로 나눠 설명 드리겠습니다. 


import 부분을 보시면, 어노테이션도 일종의 클래스로 분리 되기 때문에 사용하고자 하는 어노테이션을 import에 명시해야 사용할 수 있습니다. 기본적으로 JPA API를 지원하기 때문에 공통적으로 사용할 수 있는 어노테이션의 경우 javax.persistence 패키지에 선언된 어노테이션을 가져옵니다. 그리고 하이버네이트 특유의 어노테이션 지원을 위해 org.hibernate.annotations 패키지에서 필요한 패키지를 가져옵니다. 


class 부분은 Entity 어노테이션으로 시작합니다. 이 것은 클래스가 영속화가 가능하다는 것을 표시합니다. Table 어노테이션은 필수 사항이 아닙니다. 하이버네이트에서는 table 어노테이션을 사용하지 않으면, 자동적으로 클래스 이름을 테이블명으로 지정해 사용합니다. 하지만, Table 어노테이션을 이용하 테이블명을 직접 지정할 수 있습니다. NamedQueries는 기존의 맵핑 문서를 작성하면서 보았던 사용자 지정 쿼리입니다. 이 부분은 하이버네이트에서 어노테이션을 사용할 때 나타나는 단점 중 하나로, 네임드 쿼리를 다른 파일로 분리해 둘 곳이 없기 때문에 발생하는 문제 입니다. 이 문제는 JPA EntityManager를 사용하면 네임트 쿼리를 xml파일로 내보내 해결할 수 있습니다. 


attribute 부분에서는 컬럼의 속성들을 Id, Column, Index, ManyToOne, JoinColumn 어노테이션을 이용해 기존 맵핑 문서에서 정의한 내용들을 손쉽게 작성하고 있는 것을 확인 할 수 있습니다. Column 어노테이션의 name 값을 설정해 Table 내의 컬럼명을 지정할 수 있습니다. 이 값을 지정하지 않으면, 하이버네이트에서는 자동으로 속성명을 컬럼명으로 사용하게 됩니다.



import java.util.HashSet;

import java.util.Set;


import javax.persistence.*;


import org.hibernate.annotations.Index;


@Entity

@Table(name="ARTIST")

@NamedQueries({

    @NamedQuery(name="com.oreilly.hh.artistByName", 

        query="from Artist as artist where upper(artist.name) = upper(:name)")

})

public class Artist {


    @Id

    @Column(name="ARTIST_ID")

    @GeneratedValue(strategy=GenerationType.AUTO)

    private Integer id;

    

    @Column(name="NAME",nullable=false,unique=true)

    @Index(name="ARTIST_NAME",columnNames={"NAME"})

    private String name;


    @ManyToMany

    @JoinTable(name="TRACK_ARTISTS", 

               joinColumns={@JoinColumn(name="TRACK_ID")},

               inverseJoinColumns={@JoinColumn(name="ARTIST_ID")})

    private Set<Track> tracks;


    @ManyToOne

    @JoinColumn(name="actualArtist")

    private Artist actualArtist;


    public Artist() {}


    public Artist(String name, Set<Track> tracks, Artist actualArtist) {

        this.name = name;

        this.tracks = tracks;

        this.actualArtist = actualArtist;

    }


    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 Artist getActualArtist() {

        return actualArtist;

    }


    public void setActualArtist(Artist actualArtist) {

        this.actualArtist = actualArtist;

    }


    public Set<Track> getTracks() {

        return tracks;

    }


    public void setTracks(Set<Track> tracks) {

        this.tracks = tracks;

    }


    public String toString() {

        StringBuilder builder = new StringBuilder();


        builder.append(getClass().getName()).append("@");

        builder.append(Integer.toHexString(hashCode())).append(" [");

        builder.append("name").append("='").append(getName()).append("' ");

        builder.append("actualArtist").append("='").append(getActualArtist());

        builder.append("' ").append("]");

      

        return builder.toString();

    }

}


다른 객체의 경우도 위와 같은 방법을 이용해 어노테이션을 사용한 자바 객체로 변경할 수 있습니다. 그럼 6장에 나오는 복합 유저 타입 클래스는 어떻게 어노테이션을 지정해야 할까요? 그것은 @Embedded 어노테이션을 복합 유저 타입 클래스에 명시해 주면 됩니다. 



Posted by 빌리 :