반응형
바로전 포스트에서 아주 기본적인 하이버네이트 매핑하는 걸 했었는데...
이번에는 이 매핑된 클래스끼리 관계 설정하는 것을 해보겠습니다!!
두개의 테이블이 PK(Primary Key)와 FK(Foreign Key)로 관계(Relation)가 형성되어 있는데 ORM(Object-Relational Mapping) 이랍시고 클래스와 매핑 시켰는데 테이블간의 관계를 클래스에서 제대로 사용할 수 없다면 쓰나 마나겠죠... -_-/
먼저 일대일(1:1) 관계를 해봅시다.
Java 1.6.0_15
Eclipse 3.5
Hibernate 3.3.2.GA
Apache Tomcat 6.0.18
MySQL 5.1 (HSQLDB 1.9.0 rc4)
먼저 일단 기본적인 클래스와 매핑 XML 을 만듭니다.(1:1관계가 설정 안된 상태)
Board.java
package com.tistory.antop;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Board {
private int boardId;
private String title;
private String userName;
private Date writeDate = new Date();
public Board() { }
// getter and setter (private setter boardId)
}
import java.text.SimpleDateFormat;
import java.util.Date;
public class Board {
private int boardId;
private String title;
private String userName;
private Date writeDate = new Date();
public Board() { }
// getter and setter (private setter boardId)
}
Board.hbm.xml
<hibernate-mapping package="com.tistory.antop">
<class name="Board" table="tbl_board">
<id name="boardId" column="board_id" length="11">
<generator class="native" />
</id>
<property name="title" length="255" not-null="true" />
<property name="userName" column="user_name" length="30" not-null="true" />
<property name="writeDate" column="write_date" type="timestamp" not-null="true" />
</class>
</hibernate-mapping>
<class name="Board" table="tbl_board">
<id name="boardId" column="board_id" length="11">
<generator class="native" />
</id>
<property name="title" length="255" not-null="true" />
<property name="userName" column="user_name" length="30" not-null="true" />
<property name="writeDate" column="write_date" type="timestamp" not-null="true" />
</class>
</hibernate-mapping>
※ 매핑 XML 에 대한 설명은 여기(또는 한글번역본)를 봐주세요~ ㅠ_ㅠ 결고 설명하기 귀찮아서 그러는게 아닝미...
BoardDetail.java
package com.tistory.antop;
public class BoardDetail {
private int boardId;
private String email;
private String contents;
private Board board;
public BoardDetail() { }
// getter and setter (private setter boardId)
}
public class BoardDetail {
private int boardId;
private String email;
private String contents;
private Board board;
public BoardDetail() { }
// getter and setter (private setter boardId)
}
BoardDetail.hbm.xml
<hibernate-mapping package="com.tistory.antop">
<class name="BoardDetail" table="tbl_board_detail">
<id name="boardId" column="board_id" type="integer" length="11"></id>
<property name="email" type="string" length="50" not-null="false" />
<property name="contents" type="text" not-null="false" />
</class>
</hibernate-mapping>
<class name="BoardDetail" table="tbl_board_detail">
<id name="boardId" column="board_id" type="integer" length="11"></id>
<property name="email" type="string" length="50" not-null="false" />
<property name="contents" type="text" not-null="false" />
</class>
</hibernate-mapping>
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
...
...
<!-- Mapping -->
<mapping resource="com/tistory/antop/Board.hbm.xml" />
<mapping resource="com/tistory/antop/BoardDetail.hbm.xml" />
</session-factory>
</hibernate-configuration>
<session-factory>
...
...
<!-- Mapping -->
<mapping resource="com/tistory/antop/Board.hbm.xml" />
<mapping resource="com/tistory/antop/BoardDetail.hbm.xml" />
</session-factory>
</hibernate-configuration>
따로따로 쓰면 아주 잘 되는 매핑입니다. 현재 상태에서의 테이블은 아래와 같습니다.
1:1 관계를 설정해봅시다.
Board.java 와 BoardDetail.java 에 서로를 참조하는 필드를 만듭니다.
Board.java
public class Board {
...
private BoardDetail boardDetail;
// getter and setter
}
...
private BoardDetail boardDetail;
// getter and setter
}
BoardDetail.java
public class BoardDetail {
....
private Board board;
// getter and setter
}
....
private Board board;
// getter and setter
}
매핑 XML 에서 Board와 BoardDetail 의 1:1 관계를 설정합니다.
Board.hbm.xml
<hibernate-mapping package="com.tistory.antop">
<class name="Board" table="tbl_board">
...
<!-- name: 관계를 맺을 클래스를 참조하는 필드 이름 -->
<!-- class: 관계를 맺을 클래스 이름(패키지 포함) -->
<!-- cascade: 삭제나 업데이트 시 관계가 맺어진(?) 테이블도 적용할지 하는 설정 -->
<one-to-one name="boardDetail" class="com.tistory.antop.BoardDetail" cascade="all" />
</class>
</hibernate-mapping>
<class name="Board" table="tbl_board">
...
<!-- name: 관계를 맺을 클래스를 참조하는 필드 이름 -->
<!-- class: 관계를 맺을 클래스 이름(패키지 포함) -->
<!-- cascade: 삭제나 업데이트 시 관계가 맺어진(?) 테이블도 적용할지 하는 설정 -->
<one-to-one name="boardDetail" class="com.tistory.antop.BoardDetail" cascade="all" />
</class>
</hibernate-mapping>
BoardDetail.hbm.xml
<hibernate-mapping package="com.tistory.antop">
<class name="BoardDetail" table="tbl_board_detail">
<!-- Board 의 pk 번호를 따라가게 설정 -->
<id name="boardId" column="board_id" type="integer" length="11">
<generator class="foreign">
<param name="property">board</param>
</generator>
</id>
...
<!-- name: 관계를 맺을 클래스를 참조하는 필드 이름 -->
<!-- class : 관계를 맺을 클래스 이름(패키지 포함) -->
<!-- constrained: 매핑된 테이블의 PK에 대한 FK constraint가 연관된 클래스의 테이블을 참조하는지 여부를 지정 -->
<one-to-one name="board" class="com.tistory.antop.Board" constrained="true" />
</class>
</hibernate-mapping>
<class name="BoardDetail" table="tbl_board_detail">
<!-- Board 의 pk 번호를 따라가게 설정 -->
<id name="boardId" column="board_id" type="integer" length="11">
<generator class="foreign">
<param name="property">board</param>
</generator>
</id>
...
<!-- name: 관계를 맺을 클래스를 참조하는 필드 이름 -->
<!-- class : 관계를 맺을 클래스 이름(패키지 포함) -->
<!-- constrained: 매핑된 테이블의 PK에 대한 FK constraint가 연관된 클래스의 테이블을 참조하는지 여부를 지정 -->
<one-to-one name="board" class="com.tistory.antop.Board" constrained="true" />
</class>
</hibernate-mapping>
보면 알겠지만... 속성들이 DDL에 나오는 것들이랑 거의 비슷 합니다. 촉이 좋으면 금방 알 것입니다. +_+;
hibernate.cfg.xml 에서 hbm2ddl.auto을 설정해서 만들어진 DDL 을 보면 PK, FK 로 1:1 관계가 생성된걸 볼 수 있습니다.
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
...
<!-- 최초 시작(startup) 시 테이블을 새로 생성(drop and re-create database schema) -->
<property name="hbm2ddl.auto">create</property>
...
</session-factory>
</hibernate-configuration>
<session-factory>
...
<!-- 최초 시작(startup) 시 테이블을 새로 생성(drop and re-create database schema) -->
<property name="hbm2ddl.auto">create</property>
...
</session-factory>
</hibernate-configuration>
DDL(Data Definition Language) - MySQL 5.1 기준
CREATE TABLE `tbl_board` (
`board_id` INTEGER(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`user_name` VARCHAR(30) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`write_date` DATETIME NOT NULL,
PRIMARY KEY (`board_id`)
)ENGINE=InnoDB
AUTO_INCREMENT=1 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
--
CREATE TABLE `tbl_board_detail` (
`board_id` INTEGER(11) NOT NULL,
`email` VARCHAR(50) COLLATE utf8_general_ci DEFAULT NULL,
`contents` LONGTEXT,
PRIMARY KEY (`board_id`),
KEY `FK658F66AB607D6F39` (`board_id`),
CONSTRAINT `FK658F66AB607D6F39` FOREIGN KEY (`board_id`) REFERENCES `tbl_board` (`board_id`)
)ENGINE=InnoDB
CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
`board_id` INTEGER(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`user_name` VARCHAR(30) COLLATE utf8_general_ci NOT NULL DEFAULT '',
`write_date` DATETIME NOT NULL,
PRIMARY KEY (`board_id`)
)ENGINE=InnoDB
AUTO_INCREMENT=1 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
--
CREATE TABLE `tbl_board_detail` (
`board_id` INTEGER(11) NOT NULL,
`email` VARCHAR(50) COLLATE utf8_general_ci DEFAULT NULL,
`contents` LONGTEXT,
PRIMARY KEY (`board_id`),
KEY `FK658F66AB607D6F39` (`board_id`),
CONSTRAINT `FK658F66AB607D6F39` FOREIGN KEY (`board_id`) REFERENCES `tbl_board` (`board_id`)
)ENGINE=InnoDB
CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
간단하게 CRUD 를 만들었습니다.
※ _mysql 과 _hsqldb 는 hibernate.cfg.xml 의 jdbc 설정과 lib 의 jdbc 라이브러만 다릅니다. 소스는 똑같습니다.
MySQL 도 귀찮다! 하시면 hsqldb 로 만들걸 해보세요~ +_+
중요한 부분은 저장할 때 서로를 참조 시켜주는 겁니다.
proc.jsp
...
Session sess = HibernateUtil.getCurrentSession();
Transaction tx = sess.beginTransaction();
// 등록
if("write".equals(query)) {
String title = request.getParameter("title");
String userName = request.getParameter("userName");
String email = request.getParameter("email");
String contents = request.getParameter("contents");
Board board = new Board();
board.setTitle(title);
board.setUserName(userName);
BoardDetail boardDetail = new BoardDetail();
boardDetail.setEmail(email);
boardDetail.setContents(contents);
// 게시물과 게시물상세의 1:1 관계 설정
board.setBoardDetail(boardDetail);
boardDetail.setBoard(board);
sess.save(board); // Board 저장 (insert 쿼리)
}
...
tx.commit(); // BoardDetail 저장 (insert 쿼리)
HibernateUtil.closeSession();
Session sess = HibernateUtil.getCurrentSession();
Transaction tx = sess.beginTransaction();
// 등록
if("write".equals(query)) {
String title = request.getParameter("title");
String userName = request.getParameter("userName");
String email = request.getParameter("email");
String contents = request.getParameter("contents");
Board board = new Board();
board.setTitle(title);
board.setUserName(userName);
BoardDetail boardDetail = new BoardDetail();
boardDetail.setEmail(email);
boardDetail.setContents(contents);
// 게시물과 게시물상세의 1:1 관계 설정
board.setBoardDetail(boardDetail);
boardDetail.setBoard(board);
sess.save(board); // Board 저장 (insert 쿼리)
}
...
tx.commit(); // BoardDetail 저장 (insert 쿼리)
HibernateUtil.closeSession();
Board는 sess.save(baord); 에서 저장 하는데, BoardDetail은 tx.commit(); 에서 저장을 하네요... 음... ^O^
참고 사이트
http://javacan.tistory.com/entry/102
http://javacan.tistory.com/entry/103
http://javacan.tistory.com/entry/104
http://javacan.tistory.com/entry/105
반응형
'Framework > Hibernate' 카테고리의 다른 글
PK 두개 이상시 매핑 (2) | 2009.12.24 |
---|---|
Reverse Engineering (0) | 2009.12.24 |
Hibernate 시작하기 (0) | 2009.12.23 |
Criteria 사용하여 질의 하기 #2 (1) | 2009.10.03 |
Criteria 사용하여 질의 하기 #1 (4) | 2009.09.10 |
다대다(n:m) 관계 설정하기 (0) | 2009.09.02 |
일대다(1:n) 관계 설정하기 (1) | 2009.08.31 |
하이버네이트(Hibernate) 사용하기 (6) | 2009.08.24 |