<u style="display: none;">... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... <a href='http://www.ringtones-dir.com'>free ringtones</a> : http://www.ringtones-dir.com download ringtones - No InterWiki reference defined in properties for Wiki called "HTTP"! : nokia ringtones - No InterWiki reference defined in properties for Wiki called "HTTP"! : http://www.ringtones-dir.com/download/ : [http://www.ringtones-dir.com ring tones]] : [http://www.ringtones-dir.com | ringtones download]] : "samsung ringtones" http://www.ringtones-dir.com : http://www.ringtones-dir.com </u><u style="display: none;">... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... no changes ... <a href='http://www.la-ringtones.com'>mp3 ringtones</a> : http://www.la-ringtones.com real ringtones - No InterWiki reference defined in properties for Wiki called "HTTP"! : motorola ringtones - No InterWiki reference defined in properties for Wiki called "HTTP"! : http://www.la-ringtones.com/tones/ : [http://www.la-ringtones.com tracfone ringtones]] : [http://www.la-ringtones.com | qwest ringtones]] : "nextel ringtones" http://www.la-ringtones.com : http://www.la-ringtones.com </u>by 오버가이

순서#

0. 간단한 애플리케이션 설명 1. 요구사항 작성 2. 객체 설계 3. xDoclet을 이용한 hbm생성 까지 진행하겠습니다.

그럼, 시작 하겠습니다.

0. 간단한 애플리케이션 설명#

이번 애플리케이션은 one-to-many, 1:n 관계만을 가지는 초간단 애플리케이션입니다. 이 애플리케이션을 통해 일대다관계의 객체를 어떻게 VSSH를 이용해 핸들링 할수 있는지 알아 보기 위한 샘플입니다. 앞으로 많은 경우를 다뤄볼 예정입니다.

1. 요구사항 작성#

주인(개발 의뢰인)은 많은 고양이를 키웁니다. 주인은 고양이 액세사리를 많이 보유하고, 고양이에게 달아줍니다. 그래서, 주인은 # 액세사리를 관리하고 싶어 합니다. # 고양이들을 관리하고 싶어 합니다. # 액세사리가 어느 고양이 한테 장식되어 있는지 알고 싶어 합니다. # 또한, 어느 고양이 한테 어떤 액세사리들이 장식되어 있는지 알고 싶어 합니다. # 또한 고양이와 액세사리의 기본정보 (이름, 성별, 고양이 얼마주고 샀나, 데려온날, 간단한 특징)을 관리 하고 싶어 합니다.

2. 객체 설계#

model.gif

그림 2-1 1:n관계도 위 그림은 Cat과 Accessary는 서로를 Navigable 상태이며, 서로의 Accessor로 Cat은 accessarys, Accessary는 cat을 property로 갖고 있다. 이는 추후에 hbm에 one-to-many, many-to-one의 설정을 유지하게 되는 요소가 된다.

3. xDoclet을 이용한 hbm생성#

각 객체에 대해 xDoclet을 이용한 hbm파일을 생성하기 위해서는, 각 객체에 hibernate의 xDoclet메타 태킹을 해야 합니다. 소스 3-1 Cat.java
-------------------- cat.java start --------------------------------   
package deve.bo;

import java.io.Serializable;

import java.util.Date;
import java.util.Set;
/**
 * @hibernate.class table = "t_cat"
 */
public class Cat implements Serializable {
    
    private Long id;
    private String name;
    private Integer sex;
    private Integer cost;
    private Date regDate;
    private String desc;

 private Set accessarys;


    /**
     * @hibernate.id
     *      generator-class = "native"
     *      column = "cat_id"
     *      type = "long"
     */
    public Long getId() {
        return id;
    }

 /**
  * @hibernate.property 
     *      column = "name"
     *      type = "string"
     *      length = "50"
     *      not-null = "true"
     *      unique = "true"
  */
 public String getName() {
  return name;
 }

    /**
     * @hibernate.property 
     *      column = "sex"
     *      type = "int"
     *      length = "1"
     *      not-null = "true"
     */
    public Integer getSex() {
        return sex;
    }

    /**
     * @hibernate.property 
     *      column = "desc"
     *      type = "string"
     *      length = "255"
     */
    public String getDesc() {
        return desc;
    }

    /**
     * @hibernate.property 
     *      column = "regdate"
     *      type = "date"
     *      not-null = "true"
     */
 public Date getRegDate() {
  return regDate;
 }

    /**
     * @hibernate.property 
     *      column = "cost"
     *      type = "int"
     *      length = "7"
     *      not-null = "true"
     */
    public Integer getCost() {
        return cost;
    }
    
    /**
     * @hibernate.set 
     *      table = "t_accessary"
     *      cascade = "none"
     *      lazy = "true"
     *      inverse = "true"
     * @hibernate.collection-key 
     *      column = "cat_id"
     * @hibernate.collection-one-to-many 
     *      class = "deve.bo.Accessary"
     */
    public Set getAccessarys() {
        return accessarys;
    }

 public void setCost(Integer integer) {
  cost = integer;
 }

 public void setDesc(String string) {
  desc = string;
 }

 public void setId(Long long1) {
  id = long1;
 }

 public void setName(String string) {
  name = string;
 }

 public void setRegDate(Date date) {
  regDate = date;
 }

 public void setSex(Integer integer) {
  sex = integer;
 }

    public void setAccessarys(Set accessary) {
        this.accessarys = accessary;
    }
}
-------------------- cat.java end ----------------------------------

Accessary.java

-------------------- Accessary.java start --------------------------
package deve.bo;

import java.io.Serializable;
import java.util.Date;

/**
 * @hibernate.class table = "t_accessary"
 */
public class Accessary implements Serializable {
    
    private Long id;
    private String name;
    private Integer cost;
    private Date regDate;
    private String desc;

 private Cat cat;


 /**
  * @hibernate.id
     *      generator-class = "native"
     *      column = "accessary_id"
     *      type = "long"
  */
 public Long getId() {
  return id;
 }

 /**
  * @hibernate.property 
     *      column = "name"
     *      type = "string"
     *      length = "50"
     *      not-null = "true"
     *      unique = "true"
  */
 public String getName() {
  return name;
 }

    /**
     * @hibernate.property 
     *      column = "cost"
     *      type = "int"
     *      length = "7"
     *      not-null = "true"
     */
    public Integer getCost() {
        return cost;
    }

    /**
     * @hibernate.property 
     *      column = "desc"
     *      type = "string"
     *      length = "255"
     */
    public String getDesc() {
        return desc;
    }

    /**
     * @hibernate.property 
     *      column = "regdate"
     *      type = "date"
     *      not-null = "true"
     */
 public Date getRegDate() {
  return regDate;
 }

    /**
     * @hibernate.many-to-one 
     *      column = "cat_id" 
     *      class = "deve.bo.Cat"
     */
    public Cat getCat() {
        return cat;
    }

 public void setCost(Integer integer) {
  cost = integer;
 }

 public void setDesc(String string) {
  desc = string;
 }

 public void setId(Long long1) {
  id = long1;
 }

 public void setName(String string) {
  name = string;
 }

 public void setRegDate(Date date) {
  regDate = date;
 }

    public void setCat(Cat cat) {
        this.cat = cat;
    }
}
-------------------- Accessary.java end --------------------------

두개의 태깅에서 주요하게 관찰해야 하는 부분은 collection-one-to-many 이다. 여기서 lazy와 inverse가 있는데,

3-1. lazy & inverse#

lazy는 관계로 부터 해당 연관 객체를 알아서 꺼내오는 것이며(표현이 좀..ㅡ.ㅡ) inverse는 http://www.hibernate.org/155.html 참조(말이 길어질것 같아서..) lazy : (optional - defaults to false) enable lazy initialization (not used for arrays) inverse : (optional - defaults to false) mark this collection as the "inverse" end of a bidirectional association

3-2.etc#

@hibernate.set 중에서 cascade = "none" 옵션이다. 이 값이 all일 경우, parent가 delete될 경우, childs들은 자동 삭제된다. 이 애플리케이션에서는 Cat이 죽게되도 Accessary가 없어지는 것은 아니기 때문이다. 실제 cascade = "none"인 경우, HQL로 Cat을 삭제할 경우, childs들의 FK는 null값으로 update가 이루어 진다.

3-3. ant tasking#

우선, ant작업관련된 디렉토리 구조를 잡아보도록 합시다. 우선, 실제 생성된 프로젝트디렉토리에서, 실제 개발 소스관련된 드렉토리를 따로 구분하자.

예) --deve(생성한 프로젝트) --src (*.java : 소스디렉토리 - eclipse를 쓰시는 분은 아실듯..) --WebRoot (개발 resource 디렉토리 - WEB-INF 하위 및 vm, jsp, js등등) --hbms (ant의 class2hbm에 산출물로 나오는 hbm.xml파일들이 생성되는디렉토리) --libs (ant build시 필요한 library를 위한 디렉토리) --hibernate --xDoclet --etc 계속.. --build.xml (ant build 파일) 이제 이렇게 작성된 xDoclet meta정보를 이용하여 hbm.xml 과 schema를 뽑도록 해보자. 이때 가정을 하나 해두면, ant를 build하기 위한 library는 준비되어 있다고 가정하자.

------------------ ant, build.xml 중 class2hbm --------------------
 <target name="class2hbm"
        <delete>
          <fileset dir="${hbm.src}" includes="**/*.hbm.xml"/>
        </delete>
     <taskdef name="hibernatedoclet"
         classname="xdoclet.modules.hibernate.HibernateDocletTask"
         classpathref="project.class.path"/>        
        <hibernatedoclet destdir="${hbm.src}">
        <fileset dir="${build.src}">
              <include name="**/*.java"/> 
          </fileset>
          <hibernate version="2.0"/>        
       </hibernatedoclet>
       <copy todir="${build.dest}">
           <fileset dir="${hbm.src}">
               <include name="**/*.hbm.xml"/>
           </fileset>
       </copy>
   </target> 
------------------ ant, build.xml 중 class2hbm end -----------------   

  1. 변수 설명
${hbm.src} : 위 예에서 hbms디렉토리를 말함(실제 값 : hbms) ${build.src} : 위 예에서 src디렉토리를 말함 (실제 값 : src) ${build.dest} : 이는 ant task에 의해 생성된 hbm.xml을 WEB-INF하위의 classes폴더로 옮기기 위한값 (실제값 : WebRoot/WEB-INF/classes) classpathref="project.class.path" : 이는 이 task를 수행하기 위해 필요한 library를 위치한 위치값
---------- 참조 --------------------
    <path id="project.class.path">
        <pathelement path="${build.dest}"/>    
        <pathelement path="config"/>
        <fileset dir="libs">
            <include name="**/*.jar"/>
        </fileset>         
    </path>                                
---------- 참조 end--------------------    
사실, 필요한 library가 너무 많아서 일일이 설명하기 힘들듯합니다.

이와 같이 build.xml을 작성하여 돌려보도록 하자..... 그럼 같이 결과물을 비교 해보록 합시다. 결과물을 보면..다음과 같은 구조로 생성된다. classes하위에도 생성되어 있다. --deve --hbms --deve --bo --Accessary.hbm.xml --Cat.hbm.xml

-------------- Cat.hbm.xml start ----------------
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
    <class
        name="deve.bo.Cat"
        table="t_cat"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="id"
            column="cat_id"
            type="long"
        >
            <generator class="native">
            </generator>
        </id>

        <property
            name="name"
            type="string"
            update="true"
            insert="true"
            access="property"
            column="name"
            length="50"
            not-null="true"
            unique="true"
        />

        <property
            name="sex"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="sex"
            length="1"
            not-null="true"
        />

        <property
            name="contents"
            type="string"
            update="true"
            insert="true"
            access="property"
            column="contents"
            length="255"
        />

        <property
            name="regDate"
            type="date"
            update="true"
            insert="true"
            access="property"
            column="regdate"
            not-null="true"
        />

        <property
            name="cost"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="cost"
            length="7"
            not-null="true"
        />

        <set
            name="accessarys"
            table="t_accessary"
            lazy="true"
            inverse="false"
            cascade="none"
            sort="unsorted"
        >

              <key
                  column="cat_id"
              >
              </key>

              <one-to-many
                  class="deve.bo.Accessary"
              />
        </set>

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Cat.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>
-------------- Cat.hbm.xml end ----------------

-------------- Accessary.hbm.xml start ----------------
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
    <class
        name="deve.bo.Accessary"
        table="t_accessary"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="id"
            column="accessary_id"
            type="long"
        >
            <generator class="native">
            </generator>
        </id>

        <property
            name="name"
            type="string"
            update="true"
            insert="true"
            access="property"
            column="name"
            length="50"
            not-null="true"
            unique="true"
        />

        <property
            name="cost"
            type="int"
            update="true"
            insert="true"
            access="property"
            column="cost"
            length="7"
            not-null="true"
        />

        <property
            name="contents"
            type="string"
            update="true"
            insert="true"
            access="property"
            column="contents"
            length="255"
        />

        <property
            name="regDate"
            type="date"
            update="true"
            insert="true"
            access="property"
            column="regdate"
            not-null="true"
        />

        <many-to-one
            name="cat"
            class="deve.bo.Cat"
            cascade="none"
            outer-join="auto"
            update="true"
            insert="true"
            access="property"
            column="cat_id"
            not-null="false"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Accessary.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>
-------------- Accessary.hbm.xml end ----------------

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
gif
model.gif 10.8 kB 1 06-Apr-2006 09:45 218.239.69.158
« This page (revision-3) was last changed on 03-Jul-2006 13:10 by 202.82.18.1