- 1-1 관계
- n-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이 없다면 존재할수 없지만,private int id;
private String title;
private ArticleDetail detail;
}
public class ArticleDetail { //연관의 자식이 되는 클래스
private int id;
private Article article;
private String content;
}
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객체도 함께 저장(수정)된다.<id name="id" column="ID">
<generator class="identity" />
</id>
...
<one-to-one name="detail" class="ArticleDetail"
cascade="save-update,delete" />
</class>
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 속성사용.<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>
자식은 부모의 키값을 자신의 키 값으로 사용함. -> 식별자 생성기로 ' 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은 저장되지 않는다.ArticleDetail detail = new ArticleDetail();
article.setDetail(detail);
detail.setArticle(detail);
..
session.save(article);
Article만 읽어와도 ArtileDetail를 사용할수 있다.
Article article = (Article) session.get(Article.class, new Integer(10));
ArticleDetail detail = article.getArticleDetail();
ArticleDetail detail = article.getArticleDetail();
cascade속성에 delete가 포함되어있다면 Article를 삭제하면 1-1관계를 맺고있는 ArticleDetail 도 삭제된다.
Article article = (Article) session.get(Article.class, new Integer(10));
session.delete(article);
session.delete(article);
위 코드는 다음같이 두개의 쿼리가 실행된다.
delete from ARTICLE_DETAIL where ARTICLE_ID = 10
delete from ARTICLE where ID = 10
delete from ARTICLE where ID = 10
외부 키를 사용한 1-1 관계
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 클래스와 연관된다고 지정하고 있음.<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>
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;
..
}
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 속성은 조인 테이블의 이름을 명시.<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>
<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);
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);
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 제약조건위반
session.save(delivery); // not-null 제약조건위반
<join> 태그의 optional속성 값을 true 로 하며, <join>태그를 통해 연관된 프로퍼티의 값이 null이 아닌 경우에만
조인 테이블에 값을 저장한다.
댓글을 달아 주세요