'Hibernate'에 해당되는 글 6건

  1. 2010.06.04 Hibernate 1-1관계
  2. 2010.06.01 Hibernate의 컴포넌트
  3. 2010.06.01 복합 키 매핑 처리
관계에 따른 매핑 방법
  • 1-1 관계
  • n-1 관계
1-1 관계
세가지 방법
  1. 동일한 키값을 갖는 경우
  2. 한 테이블의 주요 키 값을 다른 테이블에서 외부 키로 참조하는 경우
  3. 조인 테이블을 이용하는 경우
동일한 키 값을 갖는 1-1 관계
주요키를 사용한 1-1연관의 예
public class Article { //연관의 부모가 되는 클래스
  private int id;
  private String title;
  private ArticleDetail detail;
}

public class ArticleDetail { //연관의 자식이 되는 클래스
  private int id;
  private Article article;
  private String content;
}
ArticleDetail은 Article이 없다면 존재할수 없지만,
Article이 삭제된다도 함께 삭제 되지 않는다.
<class name="Article" table="ARTICLE">
  <id name="id" column="ID">
    <generator class="identity" />
  </id>
  ...
  <one-to-one name="detail" class="ArticleDetail"
    cascade="save-update,delete" />
</class>
cascade속성, Article객체가 저장(수정)될때 1-1연관으로 설정한 detail객체도 함께 저장(수정)된다.
cascade속성을 명시하지 않으면 Article이 저장되어도 ArticleDetail은 저장되지 않는다.
save-update 로 명시하지 않은 경우 Article과 연관된 ArticleDetail  객체를 저장하기 위해서는 Session.save(), Session.update()
에 ArticleDetail객체를 전달해야함.

자식에서 부모로의 1-1연관
<class name="ArticleDetail" table="ARTICLE_DETAIL">
  <id name="id" column="ARTICLE_ID">
    <generator class="foreign">
      <param name="property">article</param>
    </gegerator>
  </id>
  <one-to-one name="article" class="Article" constrained="true" />
  ..
</class>
cascade대신 constrained 속성사용.
자식은 부모의 키값을 자신의 키 값으로 사용함. -> 식별자 생성기로 ' foreign'를 사용.
constrained="true"는 프로퍼티의 키값이 외부 키에 의해 제약받는것을 의미. -> "article" 프로퍼티의 키값을 ArticleDetail의 키값으로 사용한다는 뜻.

1-1 연관을 맺은후
Article article = new Article();
ArticleDetail detail = new ArticleDetail();
article.setDetail(detail);
detail.setArticle(detail);
..
session.save(article);
cascade 속성을 명시하지 않으면, Article객체가 저장될때 ArticleDetail은 저장되지 않는다.
Article만 읽어와도 ArtileDetail를 사용할수 있다.
Article article = (Article) session.get(Article.class, new Integer(10));
ArticleDetail detail = article.getArticleDetail();

cascade속성에 delete가 포함되어있다면 Article를 삭제하면  1-1관계를 맺고있는 ArticleDetail 도 삭제된다.
Article article = (Article) session.get(Article.class, new Integer(10));
session.delete(article);

위 코드는 다음같이 두개의 쿼리가 실행된다.
delete from ARTICLE_DETAIL where ARTICLE_ID = 10
delete from ARTICLE where ID = 10

외부 키를 사용한 1-1 관계
MEMBER와 MEMBER_DETAIL은 다른 키값을 가지는 대신
MEMBER는 외부 키를 이용해   MEMBER_DETAIL 과 1-1연관을 맺는다.
<class name="Member" table="MEMBER">
  <id name="id" coloumn="ID">
    <genrator class="identity" />
  </id>
  <property name="usernmae' column="USERNAME" />
  <many-to-one name="detail"
    class="MemberDetail"
    column="MEMBER_DETAILEID"
    unique="true"
    cascade="save-update, delete" />
</class>

<class name="MemberDetail" table="MEMBER_DETAIL">
  <id name="id" column="ID">
    <generator class="identity" />
  </id>
  ...
  <one-to-one name="member" class="Member" property-ref="detail" />
</class>
<many-to-one> 은  detail 프로퍼티가 MEMBER_ARTICLEID칼럼과 매핑되며 MEMBER_DETAILID 칼럼은 MemberDetail 클래스와 연관된다고 지정하고 있음.
MemberDetail 클래스는 MEMBER_DETAIL 테이블과 매핑되므로, 결국 MEMBER 테이블의 MEMBER_DETAILEID 칼럼은 MEMBER_DETAIL 테이블의  ID칼럼을 참조하게 된다.

Member 객체가 저장/삭제될때 MemberDetail  객체도 저장/삭제야 하므로 cascade 속성을 save-update, delete로 지정.
하나의 Member객체는 고유의 MemberDetail 객체와 연관되므로 unique 속성을  "true"로 지정.

조인 테이블을 이용한 1-1관계

DELIVERY_ORDER 테이블의 제약
DELIVERYID - DEVLIERY 테이블의 주요키로 참조하며, 이칼럼 자체는 주요키가 된다.
ORDERINFO - ORDER 테이블의 주요키를 외부 키로 참조하며 1-1연관의 의미를 지키기 위해 제약 조건을 갖는다.

DELIVERY  테이블에서 ORDER 테이블로의 관계가 1-1이므로 Deliver 클래스는 Order타입의 필드를 포함하게 된다.
public class Delivery {
  private Integer id;
  private Order order;
  ..
}

조인 테이블을 사용하여, 1-1관계를 명시한 경우
<class name="Delivery" table="DELIVERY">
  <id name="id" column="ID">....</id>
 
  <join table="DELIVERY_ORDER" optional="true"
    <key coulumn="DELIVERYID" />
    <many-to-one name="order"
      column="ORDERINFOID" not-null="true" unique="true" />
  </join>
</class>

<class name="Order" table="ORDERINFO">....</class>
<join> 태그의 table 속성은 조인 테이블의 이름을 명시.
<key> 태그의 column속성은 조인 테이블에서 Delivery  클래스와 연관된 칼럼을 명시. (DELIVERYID)
<many-to-one>은 Delivery 클래스에서  Order클래스로의 연관 정보를 입력.
1-1 관계를 유지하기위해 unique속성을 true로 지정.
사용은 다음과 같이.
Order order = new Order();
Delivery delivery = new Delivery();
delivery.setOrder(order);

session.save(order);
session.save(delivery);

미리 생성된 Order객체를 구한뒤, Delivery  객체와 연관지어 저장할수 있다.
Order order = session.get(Order.class, 10);
Delivery delivery = new Delivery();
delivery.setOrder(order);
session.save(delivery);

<many-to-one> 태그의 not-null속성을   true로 지정하였으므로, order 프로퍼티의 값을 지정하지 않고
delivery객체를 저장하면 제약조건 위반 에러가 발생한다.
Delivery delivery = new Delivery();
session.save(delivery); // not-null 제약조건위반

<join> 태그의 optional속성 값을  true 로 하며, <join>태그를 통해 연관된 프로퍼티의 값이 null이 아닌 경우에만
조인 테이블에 값을 저장한다.
저작자 표시
신고
Posted by 영겁회귀
EMOPLOYEE 테이블이 스키마가 다음과 같을때
 EMPLOYEE
 ID
 KOR_SURNAME
 KOR_NAME
 ENG_SURNAME
 ENG_NAME

<component> 태크로 컴포넌트 매핑하기

<class name="Employee" table="EMPLOYEE">
  <id name="id" column="ID" type="int">
    <generator class="identity" />
  </id>

  <component name="korName" class="Name">
    <property name="surname" column="KOR_SURNAME" />
    <property name="name" column="KOR_NAME" />
  </component>

  <component name="engName" class="Name">
    <property name="surname" column="ENG_SURNAME" />
    <property name="name" column="ENG_NAME" />
 </component>
</class>
<component>의 name은 프로퍼티의 이름,  class는 값 타입으로 사용되는 클래스를 의미.
korName프로퍼티의 surname프로퍼티는  KOR_SURNAME칼럼과 매핑된다.

<component>로  매핑되는 클래스도 기본 생성자를 제공해야 함
public class Name {
  private String surname;
  private String name;

  public Name(String surname, String name) {
    this.surname = surname;
    this.name = name;
  }

  public Name() {}

  public void setName() ....

  public String getSurname() ....

  ..
}

example
Employee emp = new Employee();
Name korName = new Name("박", "지성");
Name engName = new Name("Park", "Jisung");
emp.setKorName(korName);
emp.setEngName(engName);
session.save(emp);

Employee emp = (Employee)session.get(Employee.clss, new Integer(1));
Name korName = emp.getKorName();
korName.getSurName();
....

컴포넌트에서 부모객체 참조하기

public class Name {
  private Employee employee;
 
  public Employee getEmployy() {
    return employee;
  }

  public void setEmployee(Employee employee) {
    this.employee = empoyee;
  }

  ..
}

<parent> 로 부모객체를 명시
<class name="Employee" table="EMPLOYEE">
  ..
  <component name="forName" class="Name">
    <parent name="employee" />
    <property name="surname" column="KOR_SURNAME" />
    ..
  </component>
</class>

example
Employee emp = (Employee) session.get(Employee.class, new Integer(1));
Name korName = emp.getKorName();
..
korName.getEmployee();

컴포넌트 중첩
<class name="Employee" table="EMPLOYEE">
  ..
  <component name="korName" class="Name">
    <property name="surName" column="KOR_SURNAME" />
    <property name="name" column="KOR_NAME" />
  
    <component name="familyInfo" class="FamilyInfo">
      <property name="origin" column="FAMILY_ORIGIN" />
      ..
    </component>
  </component>
</class>

 

저작자 표시
신고
Posted by 영겁회귀
<id> 태그 대신에 <composite-id>태그를 사용하여 주요 키 칼럼에 대한 매핑을 설정해야함.
<class name="SecurityNoInfo" table="SECURITY_NON_INFO">
  <compoiste-id>
    <key-property name="securityNo1" column="SECNO1" />
    <key-property name="securityNo2" column="SECNO2" />
  </composite-id>

  <property name="name" column="NAME" />
</class>
<key-property>는 복합키로 사용된ㄴ 칼럼들과 클래스 프로퍼티 사이의 매핑 정보를 설정.

복합키를 사용하는 클래스는 java.io.Serializable 인터페이스를 구현해야함
해당 클래스의 객체가 식별자 값으로도 사용되기 때문.
public class SecurityNoInfo implements Serializable {
  ...
}

SecurityNoInfo sni = new SecurityNoInfo();
sni.setSecurityNo1("12334");
sni.setSecurityNo2("12345");
SecurityNoInfo loaded = (SecurityNoInfo) session.get(SecurityNonInfo.class, sni);
  Object load(Class theClass, Serializable id)
          Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.
SecurityNoInfo의 객체가 키값으로 사용됨.
식별자로 사용한 객체에 값을 저장할수도 있음
session.loaded(sni, sni);

복합 키 클래스
public class SecurityNoInfo implements Serializable {
  private String securityNo1;
  private String securityNo2;

 //get/set methods...
}

복합키를 저장하기 위하여 별도의 클래스가 존재한다면
SecurityNoInfo 클래스가 복합키를 위한 식별자로 사용할수 있도록 변경가능
public class SecurityNoInfo {
  private SecurityNoKey id;
  private String name;
  ..
  //get/set methods

  // equals / hashCode 메소드 구현
}
식별값을 표현하기 위해 SecurityNoInfo 클래스를 사용할 필요없음 -> Serializable 구현필요없음

<composite-id>태그에서 식별자로 사용할 클래스를 지정해 준다.
<class name="SecurityNoInfo" table="securityNoInfo">
  <composite-id name="id" class="SecurityNoKey">
    <key-composite name="securityNo1" column="securityNo1" />
    <key-composite name="securityNo2" column="securityNo2" />
  </composite-id>

  <property name="name" />
</class>
SecurityNoInfo 클래스의 식별자는 SecurityNoKey  클래스로 표현되며, SecurityNoKey클래스의 객체를 Session.get()/Session.load()  메소드에 식별자(파라미터)로 전달할수 있다.
SecurityNoKey key = new SecurityNoKey();
key.setSecurityNo1.set("12234");
key.setSecurityNo2.set("12311");
SecurityNoInfo sni = (SecurityNoInfo) session.get(SecurityNoKey.class, key);


저작자 표시
신고
Posted by 영겁회귀

티스토리 툴바