mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-01 15:29:11 +00:00
573 lines
33 KiB
XML
573 lines
33 KiB
XML
|
<chapter id="quickstart">
|
||
|
<title>Tomcat으로 빠른 시작</title>
|
||
|
|
||
|
<sect1 id="quickstart-intro" revision="2">
|
||
|
<title>Hibernate 시작하기</title>
|
||
|
|
||
|
<para>
|
||
|
이 튜토리얼은 웹 기반의 어플리케이션 용 Apache Tomcat 서블릿 컨테이너에 대한 Hibernate 3.0 셋업을
|
||
|
설명한다(우리는 버전 4.1을 사용했다. 5.0에 대한 차이점들은 적을 것이다). Hibernate는 모든 주요 J2EE
|
||
|
어플리케이션 서버들의 관리되는 환경에서 잘 동작하고, 또는 심지어 스탠드얼론 어플리케이션들에서도 잘 동작
|
||
|
한다. 이 튜토리얼에 사용되는 데이터베이스 시스템은 PostgreSQL 7.4이고, 다른 데이터베이스에 대한 지원은
|
||
|
단지 Hibernate SQL dialect 구성과 커넥션 프로퍼티들을 변경시키는 것에만 관계된다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
먼저 우리는 모든 필수적인 라이브러리들을 Tomcat 설치 장소에 복사해야 한다. 우리는 이 튜토리얼을 위해 별도의
|
||
|
웹 컨텍스트(<literal>webapps/quickstart</literal>)를 사용하며, 따라서 우리는 전역 라이브러리 검색 경로
|
||
|
(<literal>TOMCAT/common/lib</literal>)와 <literal>webapps/quickstart/WEB-INF/lib</literal>
|
||
|
(JAR 파일들의 경우)와 <literal>webapps/quickstart/WEB-INF/classes</literal> 내 에 있는 컨텍스트
|
||
|
레벨에서 클래스로더 양자를 고려해야 한다. 우리는 두 개의 클래스로더 레벨들을 전역 classpath와 컨텍스트
|
||
|
classpath로서 언급한다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
이제 라이브러리들을 두 개의 classpath들에 복사하라:
|
||
|
</para>
|
||
|
|
||
|
<orderedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
데이터베이스 용 JDBC 드라이버를 전역 classpath로 복사하라. 이것은 Tomcat에 번들로구성된 DBCP 커넥션
|
||
|
풀 소프트웨어에 필요하다. Hibernate는 데이터베이스 상에서 SQL을 실행시키는데 JDBC 커넥션들을 사용하므로,
|
||
|
당신은 풀링된 JDBC 커넥션들을 제공해야 하거나, 직접 지원되는 풀들(C3P0, Proxool) 중 하나를 사용하기
|
||
|
위해 Hibernate를 구성해야 한다. 이 튜토리얼을 위해, (PostgreSQL 7.4와 JDK 1.4용) <literal>pg74jdbc3.jar</literal>
|
||
|
라이브러리를 전역 classloaders 경로로 복사하라. 만일 당신이 다른 데이터베이스를 사용하고자 원할 경우,
|
||
|
간단하게 그것의 적절한 JDBC 드라이버를 복사하라.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
그 밖의 어떤 것을 Tomcat 내의 전역 클래스로더 경로에 복사하지 말라. 또는 당신은 Log4j, commons-logging
|
||
|
그리고 다른 것들을 포함하는 여러 가지 도구들에 관련된 문제점들을 얻게 될 것이다. 각각의 웹 어플리케이션에 대해
|
||
|
컨텍스트 classpath를 사용하라. 즉 라이브러리들을 <literal>WEB-INF/lib</literal>에 복사하고, 당신 자신의 클래스들과
|
||
|
구성 파일들/프로퍼티 파일들을 <literal>WEB-INF/classes</literal>에 복사하라. 두 디렉토리들 양자는 디폴트로 컨텍스트
|
||
|
classpath 내에 있다.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Hibernate는 JAR 라이브러리로서 패키지화 되어 있다. <literal>hibernate3.jar</literal> 파일은 어플리케이션의 다른 클래스들과
|
||
|
함께 컨텍스트 classpath 속에 복사되어야 한다. Hibernate는 실행 시에 어떤 제 3의 라이브러리들을 필요로하고,
|
||
|
이것들은 <literal>lib/</literal> 디렉토리 내의 Hibernate 배포본에 번들화되어 있다; <xref linkend="3rdpartylibs"/>를
|
||
|
보라. 필요한 제3의 라이브러리들을 컨텍스트 classpath로 복사하라.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</orderedlist>
|
||
|
|
||
|
<table frame="topbot" id="3rdpartylibs">
|
||
|
<title>
|
||
|
Hibernate 제3의 라이브러리
|
||
|
</title>
|
||
|
<tgroup cols="2" rowsep="1" colsep="1">
|
||
|
<colspec colname="c1" colwidth="1*"/>
|
||
|
<colspec colname="c2" colwidth="2*"/>
|
||
|
<thead>
|
||
|
<row>
|
||
|
<entry align="center">
|
||
|
라이브러리
|
||
|
</entry>
|
||
|
<entry align="center">
|
||
|
설명
|
||
|
</entry>
|
||
|
</row>
|
||
|
</thead>
|
||
|
<tbody>
|
||
|
<row>
|
||
|
<entry>
|
||
|
antlr (필수)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 질의 파서들을 산출하는데 ANTLR을 사용하고, 이 라이브러리는 또한
|
||
|
실행 시에 필요하다.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
dom4j (필수)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 XML 구성과 XML 매핑 메타데이터 파일들을 파싱하는데 dom4j를 사용
|
||
|
한다.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
CGLIB, asm (필수)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 (Java reflection과 결합하여) 런타임 시에 클래스들을 고양시키는데
|
||
|
코드 생성 라이브러리를 사용한다.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
Commons Collections, Commons Logging (필수)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 Apache Jakarta Commons 프로젝트로부터 다양한 유틸리티 라이브러리
|
||
|
들을 사용한다.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
EHCache (필수)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 second-level 캐시를 위한 다양한 캐시 프로바이더들을 사용할 수 있다.
|
||
|
만일 구성에서 변하지 않을 경우 EHCache가 디폴트 캐시 프로바이더이다.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
Log4j (옵션)
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate는 기본 로깅 메커니즘으로서 Log4j를 사용할 수 있는, Commons Logging
|
||
|
API를 사용한다. 만일 Log4j 라이브러리가 컨텍스트 라이브러리 디렉토리 속에서 이용
|
||
|
가능하다면, Commons Logging은 Log4j와 컨텍스트 classpath 내에 있는 <literal>log4j.properties</literal>
|
||
|
구성을 사용할 것이다. Log4j에 대한 예제 properties 파일은 Hibernate 배포본에
|
||
|
번들화 되어 있다. 따라서 당신이 이면에서 무엇이 진행되는 지을 보고자 원할 경우에 log4j.jar와
|
||
|
(<literal>src/</literal>에 있는) 구성 파일을 당신의 컨텍스트 classpath 속으로 복사하라.
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
필수 여부?
|
||
|
</entry>
|
||
|
<entry>
|
||
|
Hibernate 배포본 내에 있는 <literal>lib/README.txt</literal> 파일을 살펴보라.
|
||
|
이것은 Hibernate에 배포된 제 3의 라이브러리들의 최신 목록이다. 당신은 그곳에 열거된
|
||
|
모든 필수 라이브러리들과 옵션 라이브러리들을 찾게 될 것이다(여기서 "빌드 시 필요함"은
|
||
|
당신의 어플리케이션이 아니라 Hibernate에 대한 의미임을 노트하라).
|
||
|
</entry>
|
||
|
</row>
|
||
|
</tbody>
|
||
|
</tgroup>
|
||
|
</table>
|
||
|
|
||
|
<para>
|
||
|
우리는 이제 Tomcat과 Hibernate 양자에서 데이터베이스 커넥션 풀링과 공유를 설정한다. 이것은 Tomcat이
|
||
|
(그것의 미리 빌드되어 있는 DBCP 풀링 특징을 사용하여) 풀링된 JDBC 커넥션들을 제공할 것이고, Hibernate가
|
||
|
JNDI를 통해 이들 커넥션들을 요청한다는 것을 의미한다. 달리 당신은 Hibernate로 하여금 커넥션 풀을 관리하도록
|
||
|
할 수 있다. Tomcat은 그것의 커넥션 풀을 JNDI에 바인드 시킨다; 우리는 리소스 선언을 Tomcat 메인 구성 파일인
|
||
|
<literal>TOMCAT/conf/server.xml</literal>에 추가한다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[<Context path="/quickstart" docBase="quickstart">
|
||
|
<Resource name="jdbc/quickstart" scope="Shareable" type="javax.sql.DataSource"/>
|
||
|
<ResourceParams name="jdbc/quickstart">
|
||
|
<parameter>
|
||
|
<name>factory</name>
|
||
|
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
|
||
|
</parameter>
|
||
|
|
||
|
<!-- DBCP database connection settings -->
|
||
|
<parameter>
|
||
|
<name>url</name>
|
||
|
<value>jdbc:postgresql://localhost/quickstart</value>
|
||
|
</parameter>
|
||
|
<parameter>
|
||
|
<name>driverClassName</name><value>org.postgresql.Driver</value>
|
||
|
</parameter>
|
||
|
<parameter>
|
||
|
<name>username</name>
|
||
|
<value>quickstart</value>
|
||
|
</parameter>
|
||
|
<parameter>
|
||
|
<name>password</name>
|
||
|
<value>secret</value>
|
||
|
</parameter>
|
||
|
|
||
|
<!-- DBCP connection pooling options -->
|
||
|
<parameter>
|
||
|
<name>maxWait</name>
|
||
|
<value>3000</value>
|
||
|
</parameter>
|
||
|
<parameter>
|
||
|
<name>maxIdle</name>
|
||
|
<value>100</value>
|
||
|
</parameter>
|
||
|
<parameter>
|
||
|
<name>maxActive</name>
|
||
|
<value>10</value>
|
||
|
</parameter>
|
||
|
</ResourceParams>
|
||
|
</Context>]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
우리가 이 예제에서 구성하는 컨텍스트는 <literal>quickstart</literal>로 명명되고, 그것의 베이스는
|
||
|
<literal>TOMCAT/webapp/quickstart</literal> 디렉토리이다. 임의의 서블릿들에 접근하기 위해,
|
||
|
(물론 당신의 <literal>web.xml</literal> 속에 매핑된 서블릿의 이름을 추가하여) 당신의 브라우저에서
|
||
|
<literal>http://localhost:8080/quickstart</literal> 경로를 호출하라. 당신은 또한 계속 진행하고
|
||
|
이제 공백의 <literal>process()</literal> 메소드를 가진 간단한 서블릿을 생성시킬 수 있다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
Tomcat은 이제 <literal>java:comp/env/jdbc/quickstart</literal>로 JNDI을 통해 커넥션들을 제공한다.
|
||
|
만일 당신이 실행 중인 커넥션 풀을 얻는 것에 문제가 있다면 Tomcat 문서를 참조하라. 당신이 JDBC 드라이버 예외상황
|
||
|
메시지를 얻을 경우, 먼저 Hibernate 없이 JDBC 커넥션 풀을 셋업하라. Tomcat & JDBC 튜토리얼들은
|
||
|
그 웹 서이트에서 이용 가능하다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
당신의 다음 단계는 Hibernate를 구성하는 것이다. Hibernate는 그것이 JDBC 커넥션들을 얻는 방법을 알고 있어야 한다.
|
||
|
우리는 Hibernate의 XML 기반 구성을 사용한다. properties 파일을 사용하는 다른 접근법은 거의 동일하지만 XML
|
||
|
구문이 허용하는 몇몇 특징들을 누락하고 있다. XML 구성 파일은 <literal>hibernate.cfg.xml</literal>로서
|
||
|
컨텍스트 classpath (<literal>WEB-INF/classes</literal>) 내에 위치해 있다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?>
|
||
|
<!DOCTYPE hibernate-configuration PUBLIC
|
||
|
"-//Hibernate/Hibernate Configuration DTD//EN"
|
||
|
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
|
||
|
|
||
|
<hibernate-configuration>
|
||
|
|
||
|
<session-factory>
|
||
|
|
||
|
<property name="connection.datasource">java:comp/env/jdbc/quickstart</property>
|
||
|
<property name="show_sql">false</property>
|
||
|
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
|
||
|
|
||
|
<!-- Mapping files -->
|
||
|
<mapping resource="Cat.hbm.xml"/>
|
||
|
|
||
|
</session-factory>
|
||
|
|
||
|
</hibernate-configuration>]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
우리는 SQL 명령들에 대한 로깅을 사용하지 않고 Hibernate에게 사용되는 데이터베이스 SQL direct가 무엇인지
|
||
|
그리고 (Tomcat 바인드된 풀의 JNDI 주소를 선언하여) JDBC 커넥션들을 얻는 곳을 알려준다. dialect는
|
||
|
필수적인 설정이고, 데이터베이스들은 SQL "표준"에 대한 그것들의 해석을 달리한다. Hibernate는 차이점들을
|
||
|
처리하고 모든 주요 상용 데이터베이스들 및 오픈 소스 데이터베이스들 용도의 direct들을 번들로 포함하고 있다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
<literal>SessionFactory</literal>는 단일 데이터저장소에 관한 개념이고, 여러 데이터베이스들은 여러
|
||
|
개의 XML 구성 파일들을 생성시키고 당신의 어플리케이션 속에서 여러 개의 <literal>Configuration</literal>
|
||
|
및 <literal>SessionFactory</literal> 객체들을 생성시켜서 사용될 수 있다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
<literal>hibernate.cfg.xml</literal>의 마지막 요소는 영속 클래스 <literal>Cat</literal>에 대한
|
||
|
Hibernate XML 매핑 파일의 이름으로써 <literal>Cat.hbm.xml</literal>을 선언한다. 이 파일은 데이터베이스
|
||
|
테이블(또는 테이블들)로 POJO 클래스 <literal>Cat</literal> 을 매핑시키는 메타데이터를 포함한다. 우리는
|
||
|
곧 그 파일로 되돌아 갈 것이다. 먼저 POJO 클래스를 작성하고 그런 다음 그것을 위한 매핑 메타데이터를 선언하자.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="quickstart-persistentclass" revision="1">
|
||
|
<title>첫 번째 영속 클래스</title>
|
||
|
|
||
|
<para>
|
||
|
Hibernate는 영속 클래스들에 대한 Plain Old Java Objects (POJOs, 종종 Plain Ordinary Java Objects로
|
||
|
명명된다) 프로그래밍 모형으로 가장 잘 동작한다. POJO는 공용으로 가시적인 인터페이스로부터 내부적인 표상을 은폐시켜,
|
||
|
getter와 setter 메소드들을 통해 접근가능한 클래스들의 프로퍼티들을 가진 자바빈과 꽤 유사하다(필요하다면 Hibernate는
|
||
|
또한 필드들에 직접 접근할 수 있다):
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[package org.hibernate.examples.quickstart;
|
||
|
|
||
|
public class Cat {
|
||
|
|
||
|
private String id;
|
||
|
private String name;
|
||
|
private char sex;
|
||
|
private float weight;
|
||
|
|
||
|
public Cat() {
|
||
|
}
|
||
|
|
||
|
public String getId() {
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
private void setId(String id) {
|
||
|
this.id = id;
|
||
|
}
|
||
|
|
||
|
public String getName() {
|
||
|
return name;
|
||
|
}
|
||
|
|
||
|
public void setName(String name) {
|
||
|
this.name = name;
|
||
|
}
|
||
|
|
||
|
public char getSex() {
|
||
|
return sex;
|
||
|
}
|
||
|
|
||
|
public void setSex(char sex) {
|
||
|
this.sex = sex;
|
||
|
}
|
||
|
|
||
|
public float getWeight() {
|
||
|
return weight;
|
||
|
}
|
||
|
|
||
|
public void setWeight(float weight) {
|
||
|
this.weight = weight;
|
||
|
}
|
||
|
|
||
|
}]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
Hibernate는 그것의 프로퍼티 타입들의 사용에 제약되지 않고, 자바 콜렉션 프레임웍에서의 클래스들을 포함하여, 모든
|
||
|
자바 JDK 타입들과 (<literal>String</literal>, <literal>char</literal>와 <literal>Date</literal>
|
||
|
같은) 원시타입들이 매핑될 수 있다. 당신은 그것을 값들로서, 값들을 가진 콜렉션들로서, 또는 다른 엔티티들에 대한
|
||
|
연관들로서 매핑시킬 수 있다. <literal>id</literal>는 그 클래스의 데이터베이스 식별자(프라이머리 키)를 표현하는
|
||
|
특별한 프로퍼티이고, 그것은 <literal>Cat</literal>과 같은 엔티티들에 대해 매우 권장된다. Hibernate는 내부적으로만
|
||
|
식별자들을 사용할 수 있지만, 우리는 우리의 어플리케이션 아키텍처에서 어떤 유연성을 상실하게 될 것이다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
특정 인터페이스는 영속 클래스들에 대해 구현되지 말아야 하거나 특정 루트 영속 클래스로부터 서브 클래스로 만들지 말아야 한다.
|
||
|
Hibernate는 또한 바이트 코드 처리와 같은, 어떤 빌드 시 처리를 필요로 하지 않고, 그것은 오직 자바 reflection과
|
||
|
(CGLIB를 통한) 런타임 클래스 고양에만 의존한다. 따라서 Hibernate에 대한 POJO 클래스의 어떤 의존성 없이도, 우리는
|
||
|
그것을 데이터베이스 테이블로 매핑할 수 있다.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="quickstart-mapping" revision="1">
|
||
|
<title>cat 매핑하기</title>
|
||
|
|
||
|
<para>
|
||
|
<literal>Cat.hbm.xml</literal> 매핑파일은 객체/관계형 매핑에 필요한 메타데이터를 포함한다. 메타데이터는 영속
|
||
|
클래스들의 선언과 데이터베이스 테이블들에 대한 (컬럼들과 다른 엔티티들에 대한 foreign 키 관계들에 대한) 프로퍼티들의
|
||
|
매핑을 포함한다.
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[<?xml version="1.0"?>
|
||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||
|
|
||
|
<hibernate-mapping>
|
||
|
|
||
|
<class name="org.hibernate.examples.quickstart.Cat" table="CAT">
|
||
|
|
||
|
<!-- A 32 hex character is our surrogate key. It's automatically
|
||
|
generated by Hibernate with the UUID pattern. -->
|
||
|
<id name="id" type="string" unsaved-value="null" >
|
||
|
<column name="CAT_ID" sql-type="char(32)" not-null="true"/>
|
||
|
<generator class="uuid.hex"/>
|
||
|
</id>
|
||
|
|
||
|
<!-- A cat has to have a name, but it shouldn' be too long. -->
|
||
|
<property name="name">
|
||
|
<column name="NAME" length="16" not-null="true"/>
|
||
|
</property>
|
||
|
|
||
|
<property name="sex"/>
|
||
|
|
||
|
<property name="weight"/>
|
||
|
|
||
|
</class>
|
||
|
|
||
|
</hibernate-mapping>]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
모든 영속 클래스는 식별자 속성을 가져야 한다(실제로 value-타입의 클래스들에 의존하지 않는, 엔티티들을 표현하는 유일한
|
||
|
클래스들은 엔티티을 가진 컴포넌트들로 매핑된다). 이 프로퍼티는 영속 객체들을 구별짓는데 사용된다: 만일
|
||
|
<literal>catA.getId().equals(catB.getId())</literal>가 true일 경우, 두 개의 cat들은 같고, 이 개념은
|
||
|
<emphasis>database identity</emphasis>로 명명된다. Hibernate는 (데이터베이스 시퀀스, hi/lo 식별자 테이블들,
|
||
|
그리고 어플리케이션 할당 식별자들에 대한 native 생성기들을 포함하는) 다른 시나리오들에 대해 여러 가지 식별자 생성기들을
|
||
|
번들로 갖고 있다. 우리는 UUID 생성기(데이터이스에 의해 생성된 정수 대용 키들이 선호될 것이므로, 테스트용으로만 권장됨)를
|
||
|
사용하고 또한 Hibernate 생성된 식별자 값을 위한 <literal>CAT</literal> 테이블의 <literal>CAT_ID</literal>
|
||
|
컬럼을 (테이블의 프라이머리 키로서) 지정한다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
<literal>Cat</literal>의 모든 다른 프로퍼티들은 동일한 테이블로 매핑된다. <literal>name</literal> 프로퍼티의 경우에,
|
||
|
우리는 그것을 명시적인 데이터베이스 컬럼 선언으로 매핑시켰다. 데이터베이스 스키마가 Hibernate의 <emphasis>SchemaExport</emphasis>
|
||
|
도구에 의해 매핑 선언으로부터 (SQL DDL 문장들로) 자동적으로 생성될 때 이것이 특별히 유용하다. 모든 다른 프로퍼티들은
|
||
|
Hibernate의 디폴트 설정들을 사용하여 매핑되고, 디폴트 설정들은 당신이 가장 많은 시간을 필요로 하는 것이다. 데이터베이스
|
||
|
내의 테이블 <literal>CAT</literal>은 다음과 같다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[ Column | Type | Modifiers
|
||
|
--------+-----------------------+-----------
|
||
|
cat_id | character(32) | not null
|
||
|
name | character varying(16) | not null
|
||
|
sex | character(1) |
|
||
|
weight | real |
|
||
|
Indexes: cat_pkey primary key btree (cat_id)]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
당신은 이제 수작업으로 당신의 데이터베이스 내에 이 테이블을 생성시킬 것이고, 만일 당신이 <literal>hbm2ddl</literal>
|
||
|
도구로 이 단계를 자동화 시키고자 원할 경우 <xref linkend="toolsetguide"/>를 읽어라. 이 도구는 테이블 정의, 맞춤형
|
||
|
컬럼 타입 컨스트레인트들, 유일 컨스트레인트들과 인덱스들을 포함하는, 전체 SQL DDL을 생성시킬 수 있다.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="quickstart-playingwithcats" revision="2">
|
||
|
<title>cat들에 작업하기</title>
|
||
|
|
||
|
<para>
|
||
|
우리는 이제 Hibernate의 <literal>Session</literal>을 시작할 준비가 되어 있다. 그것은 <emphasis>persistence manager</emphasis>
|
||
|
(영속 관리자)이고, 우리는 데이터베이스로 <literal>Cat</literal>들을 저장하고 데이터베이스로부터
|
||
|
<literal>Cat</literal>들을 검색하는데 그것을 사용한다. 그러나 먼저 우리는 <literal>SessionFactory</literal>로부터
|
||
|
<literal>Session</literal>(Hibernate의 작업 단위)를 얻어야 한다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[SessionFactory sessionFactory =
|
||
|
new Configuration().configure().buildSessionFactory();]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
<literal>configure()</literal> 호출은 <literal>hibernate.cfg.xml</literal> 구성 파일을 로드시키고
|
||
|
<literal>Configuration</literal> 인스턴스를 초기화 시킨다. 당신이 SessionFactory(불변적임)를 빌드하기
|
||
|
<emphasis>이전에</emphasis> 당신은 <literal>Configuration</literal>에 접근함으로써 다른 프로퍼티들을
|
||
|
설정할 수 있다(그리고 심지어 매핑 메타데이터를 변경시킬 수 있다). 우리는 어디서 <literal>SessionFactory</literal>를
|
||
|
생성시키고 우리의 어플리케이션 속에서 어떻게 그것에 접근할 수 있나?
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
<literal>SessionFactory</literal>는 대개 오직 한번만, 예를 들어 대개 <emphasis>load-on-startup</emphasis>
|
||
|
서블릿으로 시작 시에 빌드된다. 이것은 또한 당신이 당신의 서블릿들 내에 있는 인스턴스 변수 속에 그것을 유지하지 않을 것이지만
|
||
|
어떤 다른 위치에 유지시킬 것임을 의미한다. 더구나 우리는 어떤 종류의 <emphasis>Singleton</emphasis>을 필요로 하며,
|
||
|
따라서 우리는 어플리케이션 코드로 쉽게 <literal>SessionFactory</literal>에 액세스 할 수 있다. 다음에 보여진 접근법은
|
||
|
두 문제 모두를 해결한다: 시작 구성과 <literal>SessionFactory</literal>에 대한 쉬운 접근.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
우리는 <literal>HibernateUtil</literal> helper 클래스를 구현한다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[import org.hibernate.*;
|
||
|
import org.hibernate.cfg.*;
|
||
|
|
||
|
public class HibernateUtil {
|
||
|
|
||
|
private static Log log = LogFactory.getLog(HibernateUtil.class);
|
||
|
|
||
|
private static final SessionFactory sessionFactory;
|
||
|
|
||
|
static {
|
||
|
try {
|
||
|
// Create the SessionFactory
|
||
|
sessionFactory = new Configuration().configure().buildSessionFactory();
|
||
|
} catch (Throwable ex) {
|
||
|
// Make sure you log the exception, as it might be swallowed
|
||
|
log.error("Initial SessionFactory creation failed.", ex);
|
||
|
throw new ExceptionInInitializerError(ex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static final ThreadLocal session = new ThreadLocal();
|
||
|
|
||
|
public static Session currentSession() {
|
||
|
Session s = (Session) session.get();
|
||
|
// Open a new Session, if this Thread has none yet
|
||
|
if (s == null) {
|
||
|
s = sessionFactory.openSession();
|
||
|
session.set(s);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public static void closeSession() {
|
||
|
Session s = (Session) session.get();
|
||
|
if (s != null)
|
||
|
s.close();
|
||
|
session.set(null);
|
||
|
}
|
||
|
}]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
이 클래스는 static 초기자를 가진 <literal>SessionFactory</literal>를 처리할 뿐만 아니라 또한 현재의 쓰레드를
|
||
|
위한 <literal>Session</literal>을 소유하는 <literal>ThreadLocal</literal> 변수를 갖는다. 이 helper를
|
||
|
사용하려고 시도하기 전에 thread-local 변수에 대한 자바 개념을 이해해야 한다. 보다 복잡하고 강력한 <literal>HibernateUtil</literal>
|
||
|
클래스는 http://caveatemptor.hibernate.org/의 <literal>CaveatEmptor</literal>에서 찾을 수 있다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
<literal>SessionFactory</literal>는 threadsafe이고, 많은 쓰레드들이 동시에 그것에 접근할 수 있고
|
||
|
<literal>Session</literal>들을 요청할 수 있다. 하나의 <literal>Session</literal>은 데이터베이스에 대해
|
||
|
한 개의 단위 작업을 나타내는 non-threadsafe 객체이다. <literal>Session</literal>들은 <literal>SessionFactory</literal>
|
||
|
로부터 열려지고 모든 작업이 완료될 때 닫혀진다. 당신의 서블릿의 <literal>process()</literal> 메소드 내에 있는
|
||
|
예제는 다음과 같을 수 있다(예외상황 처리 없이):
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[Session session = HibernateUtil.currentSession();
|
||
|
Transaction tx = session.beginTransaction();
|
||
|
|
||
|
Cat princess = new Cat();
|
||
|
princess.setName("Princess");
|
||
|
princess.setSex('F');
|
||
|
princess.setWeight(7.4f);
|
||
|
|
||
|
session.save(princess);
|
||
|
|
||
|
tx.commit();
|
||
|
HibernateUtil.closeSession();]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
하나의 <literal>Session</literal> 내에서 모든 데이터베이스 오퍼레이션은 데이터베이스 오퍼레이션들(심지어 읽기 전용
|
||
|
오퍼레이션들 조차도)을 격리시키는 하나의 트랜잭션 내부에서 발생한다. 우리는 기본 트랜잭션 방도(우리의 경우, JDBC
|
||
|
트랜잭션들)로부터 추상화시키는데 Hibernates <literal>Transaction</literal> API 를 사용한다. 이것은 우리의
|
||
|
코드가 임의의 변경들 없이도 (JTA를 사용하는) 컨테이너-관리되는 트랜잭션들에 배치되는 것을 허용해준다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
당신이 원하는 만큼 당신이 <literal>HibernateUtil.currentSession();</literal>을 호출할 수 있고, 당신은
|
||
|
이 쓰레드의 현재 <literal>Session</literal>을 항상 얻을 것임을 노트하라. 당신은 서블릿 코드 내에서든 또는 서블릿 필터
|
||
|
내에서든 HTTP response가 전송되기 전에, 당신의 단위 작업이 완료된 후에 <literal>Session</literal>이 확실히
|
||
|
닫혀지도록 해야 한다. 두 번째 옵션의 좋은 측면은 쉬운 lazy 초기화이다: 뷰가 렌더링 될 때 <literal>Session</literal>이
|
||
|
여전히 열려져 있어서, Hibernate는 당신이 현재 객체 그래프를 네비게이트 하는 동안 초기화 되지 않은 객체들을 로드시킬 수 있다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
Hibernate는 데이터베이스로부터 객체들을 검색하는데 사용될 수 있는 다양한 메소드들을 갖고 있다. 가장 유연한 방법은 Hibernate
|
||
|
Query Language (HQL)을 사용하는 것이다. Hibernate Query Language (HQL)은 배우기가 쉽고 SQL에 대한 강력한 객체 지향
|
||
|
확장이다:
|
||
|
</para>
|
||
|
|
||
|
<programlisting><![CDATA[Transaction tx = session.beginTransaction();
|
||
|
|
||
|
Query query = session.createQuery("select c from Cat as c where c.sex = :sex");
|
||
|
query.setCharacter("sex", 'F');
|
||
|
for (Iterator it = query.iterate(); it.hasNext();) {
|
||
|
Cat cat = (Cat) it.next();
|
||
|
out.println("Female Cat: " + cat.getName() );
|
||
|
}
|
||
|
|
||
|
tx.commit();]]></programlisting>
|
||
|
|
||
|
<para>
|
||
|
Hibernate는 또한 type-safe 질의들을 공식화 시키는데 사용될 수 있는 객체-지향 <emphasis>query by criteria</emphasis>
|
||
|
API을 제공한다. 물론 Hibernate는 데이터베이스와의 모든 SQL 통신을 위해 <literal>PreparedStatement</literal>들과
|
||
|
파라미터 바인딩을 사용한다. 당신은 또한 Hibernate 직접적인 SQL 질의 특징을 사용할 수도 있거나 드문 경우에
|
||
|
<literal>Session</literal>으로부터 plain JDBC 커넥션을 얻을 수도 있다.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="quickstart-summary" revision="1">
|
||
|
<title>마지막으로</title>
|
||
|
|
||
|
<para>
|
||
|
우리는 이 작은 튜토리얼 내에서 단지 Hibernate의 표면을 훑기만 했다. 우리는 우리의 예제들 속에 어떤 서블릿 지정적 코드를
|
||
|
포함하지 않음을 노트하라. 당신이 적합한지를 알려고 할 때 당신은 당신 자신의 서블릿을 생성시켜야 하고 Hibernate 코드를
|
||
|
삽입해야 한다.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
데이터 접근 계층으로서 Hibernate는 당신의 어플리케이션에 강하게 통합됨을 염두에 두라. 대개 모든 다른 레이어들은 영속
|
||
|
메커니즘에 의존했다. 당신은 이 설계의 함축을 확실히 이해하도록 하라.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
보다 복잡한 어플리케이션 예제는 http://caveatemptor.hibernate.org/ 를 보고 http://caveatemptor.hibernate.org/에
|
||
|
있는 다른 튜토리얼들을 살펴보라.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
|
||
|
</chapter>
|