By zmzizi
Hibernate concepts for Beginners-1 #
- POJO 설계와 XDoclet 을 이용한 hbm 파일 생성
1) POJO 설계#
1. 가능한 POJO 의 property = 테이블의 컬럼 이 되도록 한다.2. POJO 의 property 들은 될 수 있으면 기본형이 아닌 객체 타입으로 선언한다.
=> 해당 컬럼의 데이터가 존재하지 않을 시(null), 기본형에는 null 타입 데이터가 존재하지 않기 때문에 매핑 에러가 난다.
3. 1:n 의 포함관계일 경우, 양쪽 모두에 관계를 정의해 두는 것이 좋다.
예를 들면 Woman(1) - Clothes(n) 관계의 POJO 가 있을 때, Woman 클래스에는 Clothes 의 컬렉션을, Clothes 클래스에는 Woman 클래스를 정의해 둠으로써 양자의 관계를 명확히 하는 것이 좋다.
2) hbm 파일 생성 : XDoclet 을 사용할 경우의 핵심 태그 및 속성들 중심으로#
1. 헤더
<?xml version="1.0" encoding="UTF-8"?>
|
2. hibernate-mapping 태그
<hibernate-mapping></hibernate-mapping>
|
hibernate-mapping 태그는 Woman.hbm.xml 파일의 최상위 태그이다.
3. class 태그
<class name="test.Woman" table="WOMAN"></class>
|
클래스 태그는 해당 POJO 클래스명과 매핑되는 테이블명을 기술한다.
4. id 태그
<id name="womanId" column="womanid" type="long" length="20" unsaved-value="null"></id>
|
테이블의 pk 가 되는 id property 를 정의하는 태그이다.
- name : id property 의 이름
- column : id property 와 매칭되는 테이블의 해당 컬럼
- type : id property 타입(기본형, 객체형 등이 올 수 있다.)
- length : id property 의 최대길이이자 컬럼의 길이
- unsaved-value : any|none|null|id_value 값이 올 수 있으며, default 값은 null 이다. 이것은, Hibernate 의 saveOrUpdate() 메써드가 호출되었을 시, 각각 save 와 update 를 판단하는 기준을 설정하는 것으로써 다음의 의미를 가진다.
- null : id 가 null 이면 save, 아니면 update
- any : 항상 save 만을 호출
- none : 항상 update 만을 호출
- id_value : 특정 id_value 일 경우에만 update
5. generator 태그
<generator class="native"></generator>
|
id 태그의 하위 태그로 항상 같이 사용된다. id 를 생성하기 위한 방법(generator)을 정의하는 태그로, increment, sequence, identity, native, assigned, foreign 등의 방법이 있다.
- increment : MySQL 의 auto increment 기능을 말한다. 이 방법이 사용가능한 DBMS 는 MySQL, PostgreSQL and DB2 등이 있다. 단, cluster 환경에서는 사용해서는 안된다.
- sequence : Oracle 에서 사용되는 sequence 기능을 말한다. DB2, PostgreSQL, Oracle, SAP DB, McKoi 의 sequence 혹은 Interbase 의 generator 를 사용한다.
- identity : DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL 에서의 identity 컬럼 을 지원한다.
- native : 기반한 데이터베이스의 종류에 따라, identity, sequence, hilo 에서 취사선택한다. 예를 들어, MySQL 의 경우 identity, Oracle 의 경우 sequence 가 자동선택된다. 단, PostgreSQL, DB2 에서의 테스트에서 native 로 할 경우 오류가 발생한다는 보고가 있었고, 이들 DBMS의 경우 increment 로 설정하니 테스트는 성공적이었다고 한다. 자세한 내용은, http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseOnDB2
의 2/5 지점의 NOTE 를 참조하길 바란다.
- assigned : save() 하기 이전에 사용자가 직접 id 값을 지정해 주는 경우이다. 예를 들어, 회원의 주민번호로 id 값을 설정할 경우일텐데, Hibernate 에서는 이런 컬럼 외에 자동생성 id 컬럼을 반드시 두는 것을 권고하고 있다.
- foreign : 연관관계에 있는 다른 POJO 의 id(즉, foreign key)를 자신의 id 로 두는 방법이다. 개인적인 의견으로는, Hibernate 라는 OR Mapping Tool 의 성격상 native 를 기본적인 generator 로 설정하되, PostgreSQL, DB2 의 테스트에서 나왔듯이 문제가 발생할 경우, 다른 generator 를 선택하는 것이 좋을 것이라 생각된다.
6. property 태그
<property name="name" type="java.lang.String" column="name" length="50"/>
|
property 태그는 POJO 클래스의 해당 property 의 각종 속성을 정의한다.
- name : property 의 이름
- type : property 의 타입(기본형 혹은 객체형)
- column : 매핑될 테이블의 해당 컬럼명
- length : property 의 최대길이이자 컬럼의 길이
7. many-to-one 태그
<many-to-one name="woman" class="test.Woman" cascade="none" outer-join="auto" column="womanid"/>
|
many-to-one 태그는 Clothes 클래스에서 Woman 클래스를 바라보는 입장, 즉, n 클래스에서 1 클래스를 정의하는 방식이다.
- name : Clothes 클래스 내에서 Woman 클래스를 property 로 정의할 때의 이름, 즉 private Woman woman; 이라고 정의 할 때의 변수명이다.
- class : Woman 클래스의 full qulified name.
- cascade : all|none|save-update|delete 의 값이 있으며, 소유관계의 클래스의 변동사항이 있을 때, 하위관계에 있는 현재 클래스도 변경될 것인지 여부를 설정한다. default 는 none 이다. all(항상 변경), none(절대 변경안함), save-update(save-update 시), delete(삭제시) 일반적으로 none 혹은 delete 가 많이 사용될텐데, 해당 Woman instance 가 삭제될 경우, 그 instance 에 연관된 Clothes 도 삭제할 것인가(delete) 아닌가(none) 의 정책결정에 달려 있다.
- outer-join : true|false|auto. default 는 auto 이며, hibernate.use_outer_join 이 세팅되었을 경우,outer join 을 할 것인지 여부를 정한다.
- column : 자신의 테이블에 참조 클래스의 fk 컬럼명을 설정한다. 대개 참조 클래스의 pk 컬럼명과 일치시킨다.
8. one-to-one 태그
1:n 관계가 아닌 1:1 관계라는 것을 제외하고는 위의 many-to-one 태그와 많이 다르지 않다. 서로 다른 속성이 존재하기는 하지만, 대부분 선택사항이기 때문에 필요시 확인만 하면 되는 수준. 단, 한가지 중요한 사항은 one-to-one 관계일 경우, 한 클래스의 id 가 다른 클래스의 id 가 되는 관계, 즉 id 태그를 설정함에 있어서, generator class="foreign" 으로 설정하도록 한다.
<class name="woman" table="WOMAN">
|
개인적으로 사용해보지 않아서 확실히 모르므로 소개만 하고 넘어감... ┌( -_-)┘
9. bag 태그
<bag name="clothes" table="CLOTHES" lazy="true" cascade="all"></bag>
|
collection 을 나타내는 태그는 set, map, list, array, bag 등이 있다.
나의 경우, 1:n 관계를 표현할 때, 포함된 컬렉션 클래스들은 모두 list 로 정의하였고, hbm 파일상의 매핑은 bag 태그를 사용하였다. list 태그를 사용해도 괜찮았겠지만, bag 태그가 좀 더 광범위하게 사용된다고 이해했기 때문에 bag 태그를 사용하였다.
- name : 컬렉션 property 의 이름
- table : 해당 컬렉션 데이터가 매핑하고 있는 테이블명
- lazy : true|false default 는 true. 늦은 초기화 설정여부를 나타낸다. 여기에서의 늦은 초기화란, 예를 들어,특정한 Woman instance 를 가져왔을 때, 그 Woman 이 가지고 있는 Clothes 데이터까지 모두 가져오지 않으며, 그 Woman instance 에서 getClothes 메써드가 호출되었을 시에 Clothes 데이터를 가져오는 것을 말한다. 즉, 실제로 해당 데이터에 접근을 했을 때, 데이터를 로딩하기 때문에, 늦은 초기화라고 부른다. 만약, 이 설정이 false 로 되어 있다면, Woman instance 를 가져오는 즉시, 포함관계의 Clothes 데이터도 가져오게 된다. 이는 불필요한 데이터 액세스를 줄이기 위한 정책적인 결정에 따른다. 그런데, 이러한 늦은 초기화가 가능한 것은 트랜잭션이 관리되는 범위까지에서이다. 즉, Hibernate 를 독립적으로 사용시에는 Session 이 닫히기 이전, Spring 과 함께 사용시에는 applicationContext.xml에서 설정한 Service Transaction 클래스 내까지만 늦은 초기화가 가능하며, 이때까지 초기화를 하지 않은 상태로 Action 클래스 혹은 JSP 화면에서 데이터를 액세스 하려고 하면 LazyInitializationException 이 발생하게 된다. 따라서, 실제로 사용해야 하는 데이터라면 반드시 동일 Session 내에서 반드시 초기화 과정을 거쳐야만 한다.
- cascade : all|none|save-update|delete|all-delete-orphan default 는 none 이며, 포함하고 있는 클래스의 변경시 컬렉션에 들어 있는 데이터들의 변경 설정을 결정한다.
10. key 태그
<key column="womanid"></key>
|
컬렉션의 fk 컬럼명. 해당 클래스에서 many-to-one 에 정의된 테이블 컬럼명이기도 하다.
11. one-to-many 태그
<one-to-many class="test.CLOTHES"/>
|
컬렉션의 데이터가 되는 클래스. full qualified name 으로 표기한다.
3) XDoclet을 사용한 hbm 파일 생성 Tips#
- hbm 파일 생성은 XDoclet 태그를 이용하여 자동생성 하는 것을 원칙으로 한다.
- Hibernate XDoclet 태그 사용은 http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html
를 참조.
- 클래스 레벨 태그는 클래스명 앞에, 메써드 레벨 태그는 getter 메써드 앞에 기술하되, 상위 태그가 위에 오도록 한다.
- 특정한 데이터 handling 등을 위해 테이블의 컬럼 이 아님에도 부득이하게 POJO 의 property 로 추가되어야 할 경우, 해당 property 에는 XDoclet 태그를 달아서는 안된다. XDoclet 태그를 달면 테이블의 컬럼과 매핑시 오류가 발생한다.
- build.xml 에 추가시켜 두면 유용한 Hibernate 관련 task
- xdoclet 사용시 필요한 library path : ${classes.home} 등 알만한 변수는 생략
<path id="xdoclet.lib.path">
|
- hbm 파일 만드는 task
<target name="make-hbm" depends="">
|
- hbm 파일의 내용대로 DBMS 에 테이블을 생성하는 task
<target name="schemaexport" depends="make-hbm">
|
- 특정 이름의 sql 파일을 실행시켜 테이블에 초기 데이터를 입력하는 task
<target name="init-sql" depends="">
|