다대다(n:m) 관계 설정하기

Posted at 2009. 9. 2. 11:05 | Posted in Framework/Hibernate
반응형
이번에는 사람과 세미나 사이의 다대다(n:m) 관계를 설정해보겠습니다. ^^;;

사람은 여러개의 세미나를 등록할 수 있고, 세미나는 여러 사람이 올 수 있죠~

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)



사람(Person)과 세미나(Person) 을 매핑 합시다~

Person.java
package com.tistory.antop;

public class Person {

    private int seq;
    private String name;
    private Gender gender;
 
    private enum Gender {
        남, 여
    }
 
    // constructor, getter and setter (private setter seq)
}

Person.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Person" table="tbl_person">
        <id name="seq">
            <generator class="native" />
        </id>
  
        <property name="name" />
        <property name="gender" />
  
    </class>
</hibernate-mapping>


Seminar.java
package com.tistory.antop;

import java.util.Date;

public class Seminar {

    private int sid;
    private String title;
    private Date sDate = new Date();
    private String area;

    // constructor, getter and setter (private setter sid)
 }

Seminar.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Seminar" table="tbl_seminar">
        <id name="sid">
            <generator class="native" />
        </id>
  
        <property name="title" />
        <property name="sDate" column="s_date" />
        <property name="area" />
  
    </class>
</hibernate-mapping>


hibernate.cfg.xml
<hibernate-configuration>
    <session-factory>
        ...

        <!-- Mapping -->
        <mapping resource="com/tistory/antop/Person.hbm.xml" />
        <mapping resource="com/tistory/antop/Seminar.hbm.xml" />

    </session-factory>
</hibernate-configuration>


관계가 맺어지지 않은 테이블이 매핑 되었습니다~



이제 n:m 관계를 맺어봅시다~

논리적(생각)으로는 두 테이블이 n:m 관계가 나오지만, 물리적(실제)으로는 n:m 관계를 만들려면 두 테이블을 이어줄 테이블이 하나 더 껴들어가야 합니다... ㅠ_ㅠ




클래스와 매핑 XML 에 n:m 관계(양방향)를 추가 합시다.

서로를 n 개만큼 참조해야하므로 Set 으로 하겠습니다.


Person.java
package com.tistory.antop;

import java.util.HashSet;
import java.util.Set;

public class Person {
   
    ...

    // person n:m seminar
    private Set<Seminar> seminars = new HashSet<Seminar>();

    public Set<Seminar> getSeminars() {
        return seminars;
    }

    public void setSeminars(Set<Seminar> seminars) {
        this.seminars = seminars;
    }

    // 세미나 등록
    public void addSeminar(Seminar s) {
        this.seminars.add(s);
    }
    
    // 세미나 취소
    public void cancelSeminar(Seminar s) {
        this.seminars.remove(s);
    }
}

Person.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Person" table="tbl_persons">
        ...

        <!-- person n:m seminar -->
        <set name="seminars" table="tbl_persons_seminars">
            <key column="seq" />
            <many-to-many class="com.tistory.antop.Seminar" column="sid" />
        </set>
 
    </class>
</hibernate-mapping> 

<set name="seminars" table="tbl_persons_seminars">
   java.util.Set 을 사용 했고 담고있을 필드는 seminars, n:m 관계를 맺어주는 테이블명은 tbl_persons_seminars

<key column="seq" />
   자기 테이블(Person)의 FK(Foreign Key) 되는 칼럼명입니다.

<many-to-many class="com.tistory.antop.Seminar" column="sid"  />
  m 관계를 맺게되는 테이블(tbl_seminar)의 클래스명과 그쪽의 FK가 되는 칼럼명입니다.


Seminar 쪽도 마친가지로 매핑해 줍니다.

Seminar.java
package com.tistory.antop;

import java.util.HashSet;
import java.util.Set;

public class Seminar {

    // person n:m seminar
    private Set<Person> persons = new HashSet<Person>();

    // 누가 이 세미나에 신청 했는지 알기위해 getter 만 public
    public Set<Person> getPersons() {
        return persons;
    }

    @SuppressWarnings("unused")
    private void setPersons(Set<Person> persons) {
        this.persons = persons;
    }
 
    // 사람(person)이 세미나 등록, 취소를 할 수 있다고 보고 세미나를 기준으로 등록 삭제는 없슴!
}

Seminar.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Seminar" table="tbl_seminars">

        ...  

        <!-- person n:m seminar -->
        <set name="persons" table="tbl_persons_seminars">
            <key column="sid" />
            <many-to-many class="com.tistory.antop.Person" column="seq" />
        </set>
  
 </class>
</hibernate-mapping>




테스트 해봅시다~

request.getParameter() 안쓰려고 스트러츠 썻는데 더 꼬여뿌렀네용 -_-;;

하이버네이트 부분은 dao 에 있습니다.




반응형

'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
일대다(1:n) 관계 설정하기  (1) 2009.08.31
일대일(1:1) 관계 설정하기  (0) 2009.08.27
하이버네이트(Hibernate) 사용하기  (6) 2009.08.24
//

일대다(1:n) 관계 설정하기

Posted at 2009. 8. 31. 16:22 | Posted in Framework/Hibernate
반응형
전 포스핑에서 1:1 관계를 설정해봤습니다.

테스트 업무는 고객(cutomer)이 문의(support)를 올리고, 관리자가 그 문의에 답변(reply)을 다는 업무입니다.

고객은 문의를 여러번 할 수 있고, 관리자는 그 문의에 여러번 답변할  수 있습니다.


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)



먼저 아무 관계가 없는 매핑을 만들어 봅시다.

Customer.java
package com.tistory.antop;

public class Customer {

    private String id;
    private String name;
    private String pwd;
    private String tel;

    // construct, getter, setter
}

Customer.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Customer" table="tbl_customers">
        <id name="id" length="20" />
        <property name="pwd" column="password" length="20" not-null="true" />
        <property name="name" length="30" not-null="true" />
        <property name="tel" length="13" not-null="false" />
    </class>
</hibernate-mapping>


Support.java
package com.tistory.antop;

public class Support {

    private int id;
    private String title;
    private String contents;

    // construct, getter, setter (private setter id)
}

Support.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Support" table="tbl_supprots">
        <id name="id" column="support_id">
            <generator class="native" />
        </id>
        <property name="title" length="255" not-null="true" />
        <property name="contents" type="text" />
    </class>
</hibernate-mapping>


Reply.java
package com.tistory.antop;

public class Reply {

    private int seq;
    private String reply;
 
    // construct, getter, setter (private setter seq)
}

Reply.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Reply" table="tbl_replays">
        <id name="seq">
            <generator class="native" />
        </id>
        <property name="reply" type="text" not-null="true" />
    </class>
</hibernate-mapping>


hibernate.cfg.xml
<hibernate-configuration>
    <session-factory>
        ...

        <!-- Mapping -->
        <mapping resource="com/tistory/antop/Customer.hbm.xml" />
        <mapping resource="com/tistory/antop/Support.hbm.xml" />
        <mapping resource="com/tistory/antop/Reply.hbm.xml" />

    </session-factory>
</hibernate-configuration>



아무런 관계(릴레이션)가 없는 테이블 3개가 매핑 되었습니다.



이제 1:n 관계를 설정 합시다.

1:1에서와 마찬가지로 서로 참조를 시켜야 합니다.
 
db 에서는 1:n 관계를 1이 되는쪽의 PK 와 n 이 되는쪽의 FK를 지정하여 관계를 설정해주고,
 
클래스로 구현하면 1이 되는 클래스 필드가 n이 되는 클래스를 n개 만큼 참조하고 있어야 합니다.

반대로 n쪽의 클래스는 1이 되는 클래스를 참조하고 있어야겠죠?


먼저 고객(customer)과 문의(support)의 1:n 관계를 설정 해봅시다.


관계를 맺을 수 있는 필드와 사용할 적절한 메소드를 추가합니다.

Customer.java
public class Customer {
    ...

    // customer 1:n support 관계를 가지는 필드
    private Set<Support> supports = new HashSet<Support>();

    public Set<Reply> getReplys() {
        return replys;
    }

    private void setReplys(Set<Reply> replys) {
        this.replys = replys;
    }

    // 문의 추가
    public void addSupport(Support support) {
        if(getSupports() == null) {
            setSupports(new HashSet<Support>());
        }
        // customer -> support 참조
        getSupports().add(support);
        // support -> customer 참조
        support.setCustomer(this);
    }
 
    // 문의 삭제
    public void delSupport(Support support) {
        getSupports().remove(support);
    }
 
    // 문의 비우기
    public void clearSupports() {
        getSupports().clear();
    }
}

Customer.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Customer" table="tbl_customers">
        ...

        <!-- customer 1:n support -->
        <set name="supports" inverse="true" cascade="all-delete-orphan">
            <key column="customer_id" />
            <one-to-many class="com.tistory.antop.Support" />
        </set>
    </class>
}

Customer 와 Support 의 1:n 관계에서 Support는 콜랙션(Collection) 형태로 참조됩니다.

Set, List, Bag, Map 등등 있는데 자세한건 여기에서 확인을... -0-

 -= <set></set> : java.util.Set 타입으로 정의합니다.
   - name : java.util.Set 타입의 필드명입니다. (Customer.java의 "private Set<Support> supports")
   - inverse : 객체간 관계의 책임을 어디에 둘지에 대한 옵션을 정의하기 위한 속성입니다.
                   즉, 한 쪽은 owner의 역할을 맡기고, 다른 한 쪽에는 sub의 역할을 맡기기 위함입니다.
   - cascade : 부모 객체에 대한 CUD를 자식 객체에도 전이할지에 대한 옵션을 정의하기 위한 속성입니다.
 -= <key column="..." /> : FK(Foreign Key)를 명시합니다. (Support 쪽의 FK)
 -= <on-to-many class="..." /> : 관계를 맺는 클래스명(패키지명포함)을 명시합니다.


Support.java
public class Support {
    ...
    // customer 1:n support 관계를 가지는 필드
    private Customer customer;
   
    public Customer getCustomer() {
        return customer;
    }

    private void setCustomer(Customer customer) {
        this.customer = customer;
    }

    // 답변 추가
    public void addReply(Reply reply) {
        if(getReplys() == null) {
            setReplys(new HashSet<Reply>());
        }
        // support -> reply 참조
        getReplys().add(reply);
        // reply -> support 참조
        reply.setSupport(this);
    }
 
    // 답변 삭제
    public void delReply(Reply reply) {
        getReplys().remove(reply);
    }
 
    // 답변 비우기
    public void clear() {
        getReplys().clear();
    }
}

Support.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Support" table="tbl_supprots">
         ...

        <!-- customer 1:n support -->
        <many-to-one name="customer" column="customer_id" class="com.tistory.antop.Customer" />
    </class>
</hibernate-mapping>

Support 쪽에서는 그냥 customer 하나만 참조하면 됩니다.


이제 문의(support)와 답변(reply)도 1:n 관계를 설정합시다! +_+/

Support.java
public class Support {
    ...

    // support 1:n reply 관계를 가지는 필드
    private Set<Reply> replys = new HashSet<Reply>();

    public Set<Reply> getReplys() {
        return replys;
    }

    private void setReplys(Set<Reply> replys) {
        this.replys = replys;
    }
}

Support.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Support" table="tbl_supprots">
        ...

        <!-- support 1:n reply -->
        <set name="replys" inverse="true" cascade="all-delete-orphan">
            <key column="support_id" />
            <one-to-many class="com.tistory.antop.Reply" />
        </set>
    </class>
</hibernate-mapping>


Reply.java
public class Reply {
    ...

    // support 1:n reply 관계를 가지는 필드
    private Support support;

    public Support getSupport() {
        return support;
    }

    public void setSupport(Support support) {
        this.support = support;
    }
}

Reply.hbm.xml
<hibernate-mapping package="com.tistory.antop">
    <class name="Reply" table="tbl_replays">
        ...

        <!-- support 1:n reply -->
        <many-to-one name="support" column="support_id" class="com.tistory.antop.Support" />
    </class>
</hibernate-mapping>


이제 문의(support)와 답변(reply)의 1:n 관계도 설정 되었습니다.




이제 CRUD 해야졍.... 배보다 배꼽이 더 크네여 아오~

이번에는 조금 제대로 만들어 보았습니다... (아주 조금입니다... 조ㄱㅡ..)

진짜 배보다 배꼽이 더 켜졌네요;;;





참고 사이트
http://docs.jboss.org/hibernate/stable/core/reference/en/html/associations.html
http://dev.anyframejava.org/anyframe/doc/core/3.1.0/corefw/guide/hibernate-persistence-mapping-association.html
http://javacan.tistory.com/entry/106


반응형

'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:1) 관계 설정하기  (0) 2009.08.27
하이버네이트(Hibernate) 사용하기  (6) 2009.08.24
//

일대일(1:1) 관계 설정하기

Posted at 2009. 8. 27. 16:58 | Posted in Framework/Hibernate
반응형

바로전 포스트에서 아주 기본적인 하이버네이트 매핑하는 걸 했었는데...

이번에는 이 매핑된 클래스끼리 관계 설정하는 것을 해보겠습니다!!

두개의 테이블이 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)
}

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>

※ 매핑 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)
}

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>


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>


따로따로 쓰면 아주 잘 되는 매핑입니다. 현재 상태에서의 테이블은 아래와 같습니다.



1:1 관계를 설정해봅시다.

Board.java 와 BoardDetail.java 에 서로를 참조하는 필드를 만듭니다.

Board.java
public class Board {
    ...
   
    private BoardDetail boardDetail;

    // getter and setter
}

BoardDetail.java
public class BoardDetail {
    ....

    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>

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>


보면 알겠지만... 속성들이 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>


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';




간단하게 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();


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
//

하이버네이트(Hibernate) 사용하기

Posted at 2009. 8. 24. 17:09 | Posted in Framework/Hibernate
반응형

Hibernate는 객체 모델링(Object Oriented Modeling)과 관계형 데이터 모델링(Relational Data Modeling) 사이의 불일치를 해결해 주는 ORM(Object Relation Mapping) 도구입니다.

Hiberbate Architecture


잘 사용하면 쿼리(sql) 하나 안쓰고 클래스의 set, get 같은것으로만 DB를 조종(?)할 수 있습니다.

하이버네이트를 이용하여 아주 간단한 CRUD[각주:1] 만 해봅시다!

Java 1.6.0_13
Hibernate 3.3.2.GA
Apache Tomcat 6.0.18
HSQLDB 1.9.0 rc4
Eclipse 3.5 + Habernate Tools


- 하이버네이트 라이브러리와 log4j 사용을 위한 properties 파일을 세팅합니다.(아래 war 파일에서 확인해주세요)


- 하이버네이트 실행에 관련된 속성 정보를 가지고 있는 hibernate.cfg.xml 파일을 만듭니다.




- hibernate.cfg.xml 파일을 저장할 위치를 설정합니다. (기본 src)



- Database 정보를 입력합니다.



- hibernate.cfg.xml 파일을 열어서 몇가지를 더 추가해줍니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
   "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
      <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="hibernate.connection.url">jdbc:hsqldb:hsql/antop</property>
      <property name="hibernate.connection.username">sa</property>
      <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>

      <!-- JDBC connection pool (use the built-in) -->
      <property name="connection.pool_size">1</property>

      <!-- For a HSQL 1.8 in-memory database, this is required -->
      <property name="connection.shutdown">true</property>
        
      <!-- Drop and re-create the database schema on startup -->
      <property name="hbm2ddl.auto">create</property>

      <!-- Echo all executed SQL to stdout -->
      <property name="show_sql">true</property>
  
      <!-- Mapping -->

   </session-factory>
</hibernate-configuration>

show_sql 프로퍼티를 true로 하면 콘솔에서 쿼리를 확인할 수 있습니다.
hbm2ddl.auto 프로퍼티는 hbm.xml 이 바뀌면 디비 테이블을 드랍시키고 다시 생성하니 주의하세요!

- 간단한 고객테이블(customer)를 매핑시켜보겠습니다. (각 컬럼의 속성은 다를겁니다... MySQL 툴로 디자인한거라...)



- Customer 클래스를 작성합니다.
package com.tistory.antop;

public class Customer {
   private int seq;
   private String id;
   private String password;
   private String name;

   public Customer() { }

   public int getSeq() {
      return seq;
   }

   // 자동으로 생성되는 번호이므로 set 금지
   private void setSeq(int seq) {
      this.seq = seq;
   }
   // getter, setter, toString()
}


customer 테이블의 seq 칼럼은 자동증가이므로 클래스에서 setter를 private으로 선언한 것을 볼 수 있습니다. +_+/


- Customer 클래스에 대해 Mapping XML 파일을 작성합니다.

해당 클래스파일(.java)에서 마우스 오른쪽버튼 클릭 → New → Other...




이렇게 파일을 만들면 쵸큼 더 쉽게 작성할 수 있습니다.

Customer.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.tistory.antop">
   <class name="Customer" table="customer">
      <!-- 기본키가 되는 필드 -->
      <id name="seq" column="SEQ">
         <!-- 자동 증가 -->
         <generator class="increment" />
      </id>
      <property name="id" column="ID" />
      <property name="password" column="PWD" />
      <property name="name" column="NAME" />
   </class>
</hibernate-mapping>

각 태그에 대한 성명은 여기를 봐주세요.


- 마지막으로 hibernate.cfg.xml 에다가 Customer.hbm.xml을 추가해줘야합니다.
...
<hibernate-configuration>
   ...

      <!-- Mapping -->
      <mapping resource="com/tistory/antop/Customer.hbm.xml"/>
  
   </session-factory>
</hibernate-configuration>


- 간단하게 customer에 관한 예제를 만들어보았습니다. 배보다 배꼽이 더 크군염 ㅠ_ㅠ



테스트는 용자만 할 수 있습니다.! +_+/




참조 사이트
http://docs.jboss.org/hibernate/stable/core/reference/en/html/
http://dev.anyframejava.org/anyframe/doc/core/3.1.0/corefw/guide/hibernate-introduction.html
http://javacan.tistory.com/entry/101


참조 문서

출처: http://cafe.naver.com/deve.cafe (문제가 된다면 삭제하겠습니다. ㅠ_ㅠ)



  1. CRUD : Create, Retrieve, Update, Delete [본문으로]
반응형

'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
일대일(1:1) 관계 설정하기  (0) 2009.08.27
//

스트러츠(Struts) 기본 세팅

Posted at 2009. 6. 22. 22:10 | Posted in Framework/Struts
반응형
이클립스에서 스트러츠를 시작하기 위한 아주아주 기본적인 세팅입니다.

이걸 해야 스트러츠를 시작할 수 있죠!! >,.<

- Eclipse Ganymede 3.4.2
- Apache Tomcat 6.0.18
- Apache Struts 1.3.10
- Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
- 텍스트 인코딩 : 글로벌 시대에 맞게 UTF-8




- File → New → Dynamic Web Project




- 스트러츠 라이브러리를 다운로드받습니다.



- WEB-INF/lib 폴더에 다 때려넣습니다.




- web.xml 을 수정합니다. 주석달린 두 부분(?)을 추가합니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">

  <display-name>BaseStruts</display-name>

  <!-- Standard Action Servlet Configuration -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>


- WEB-INF 폴더에 struts-config.xml 파일을 만듭니다. (web.xml 파일의 init-param 의 경로와 일치해야함!)

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
    <!--  Form Bean Definitions -->
    <form-beans>

    </form-beans>

    <!--  Global Exception Definitions -->
    <global-exceptions>

    </global-exceptions>

    <!-- Global Forward Definitions -->
    <global-forwards>

    </global-forwards>

    <!-- Action Mapping Definitions -->
    <action-mappings>

    </action-mappings>

    <!-- Message Resources Definitions -->
    <!-- Plug Ins Configuration -->

</struts-config>


스트러츠를 사용하기 위한 완전 아무것도 없는 프로젝트를 만들었습니다... 자! 이제 쓰세요 -_-;;




... 뭐 간단한거라도 만들어볼까요?;; 로그인 하는거 만들어봅시다 >,.<

위에서 만들었던 BaseStruts 를 Import 해서 기본 스트러츠를 세팅합시다!


- File → Import : Web → WAR File




- 프로젝트 이름 변경 하시구!




- 소스 줄줄이 작성! (너무 간단한 예제라 다 펼쳐놓기가 부끄럽군요! ㅠ_ㅠ)

뭐.. UML 은 당연히 틀렸겠죠 +_+;

클래스 다이어그램(Class Diagram)


시퀀스 다이어그램(Sequence Diagram) 


struts-config.xml


    <form-beans>
        <form-bean name="JFLogin" type="com.tistory.antop.forms.JFLogin" />
    </form-beans>

    <action-mappings>
        <action path="/JALogin" type="com.tistory.antop.actions.JALogin"
            name="JFLogin" scope="request" validate="true">
            <forward name="result" path="/result.jsp" />
        </action>
    </action-mappings>




실행은 의지를 가진 용자들은 알아서 하실꺼....



2010.01.26 - 한글 파라미터 처리를 위한 플러그인 클래스 추가
반응형

'Framework > Struts' 카테고리의 다른 글

*.jsp 접근 막기  (0) 2009.09.03
Struts 파일 업로드  (2) 2009.05.05
//

Struts 파일 업로드

Posted at 2009. 5. 5. 22:58 | Posted in Framework/Struts
반응형

Struts 에서 파일 업로드 하는 법입니다.

왜 올리냐? 앞으로의 Ctrl+C , Ctrl+V 를 위해서 -_-v

jdk 1.6.0_13
tomcat 6.0.18
struts 1.3.10

프로젝트는 struts-blank-1.3.10.war 파일 Import 해서 생성 했고, jsp 에는 struts taglib를 사용했습니다.



form.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>file upload</title>
</head>
<body>

<html:form action="/result" method="post" enctype="multipart/form-data">

subject : <html:text property="subject" /> <br />
file : <html:file property="att" /> <p />
<html:submit value="submit" />

</html:form>

</body>
</html>


struts-config.xml
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>

 <form-beans>
  <form-bean name="formFileUpload" type="antop.FormFileUpload" />
 </form-beans>

 <global-exceptions> </global-exceptions>

 <global-forwards> </global-forwards>

 <action-mappings>
  <action path="/result" type="antop.ActionFileUpload"
   name="formFileUpload" input="/form.jsp" scope="request">
   <forward name="result" path="/result.jsp"/>
  </action>

 </action-mappings>

 <message-resources parameter="MessageResources" />

 <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
  <set-property property="pathnames"
   value="/org/apache/struts/validator/validator-rules.xml,
               /WEB-INF/validation.xml" />
 </plug-in>

</struts-config>


FormFileUpload.java
package antop;

import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;

public class FormFileUpload extends ActionForm
{
  private static final long serialVersionUID = 1;

  private String subject;
  private FormFile att;

  public String getSubject() {
    return subject;
  }
  public void setSubject(String subject) {
    this.subject = subject;
  }
  public FormFile getAtt() {
    return att;
  }
  public void setAtt(FormFile att) {
    this.att = att;
  }
}


ActionFileUpload.java
package antop;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;

public class ActionFileUpload extends Action
{
  @Override
  public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response)
    throws Exception {
  
    FormFileUpload f = (FormFileUpload)form;
  
    String subject = f.getSubject();
    FormFile att = f.getAtt();

    if(att != null)
    {
      String realName = "";
      String fileName = att.getFileName();
      String fileContextType = att.getContentType();
      int fileSize = att.getFileSize();
   
      String path = "/upload";  // 업로드할 경로
      String realPath = "";
   
      /*
       * 파일 업로드 시작
      */

      InputStream in = null;
      OutputStream os = null;
   
      try
      {
        // 파일 확장자 구하기
        String ext = att.getFileName();
   
        int last = 0;
        boolean findExt = false;
    
        while((last = ext.indexOf(".")) != -1) {
          findExt = true;
          ext = ext.substring(last+1);
        }
    
        // 파일 이름 중복 방지
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String rndName = sdf.format(new java.util.Date()) + System.currentTimeMillis();
    
        // 실제 저장될 파일 이름
        realName = findExt ? rndName + "." + ext : rndName;
    
        // 실제 저장될 디렉토리 구하기
        ServletContext application = getServlet().getServletContext();
        realPath= application.getRealPath(path);
    
        // 실제로 저장될 파일 풀 경로
        File file = new File(realPath + "/" + realName); 
    
        // 저장하기(복사)
        os = new BufferedOutputStream(new FileOutputStream(file));
        in = att.getInputStream();
    
        int i;
        byte[] buffer = new byte[1024*4];
        while((i=in.read(buffer, 0, 1024*4)) != -1) {
          os.write(buffer, 0, i);
        }
   
      }
      catch(Exception e) {
        e.printStackTrace();
      }
      finally {
        try { if(os != null) os.close(); } catch (IOException ignore) { }
        try { if(in != null) in.close(); } catch (IOException ignore) { }
      }
      /*
       * 파일 업로드 끝
      */
   
        request.setAttribute("realPath", realPath);   // 실제 저장되는 풀경로
        request.setAttribute("realName", realName);   // 실제 저장된 파일 이름
        request.setAttribute("fileName", fileName);   // 업로드 했을때의 파일 이름
        request.setAttribute("fileSize", fileSize);   // 파일 사이즈
        request.setAttribute("fileType", fileContextType); // 파일 종류
      }
  
      request.setAttribute("subject", subject);   // 제목
  
      return mapping.findForward("result");
  }
}


result.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>file upload result</title>
</head>
<body>

subject : <bean:write name="subject"/> <br />
realPath : <bean:write name="realPath"/> <br />
realName : <bean:write name="realName"/> <br />
fileName : <bean:write name="fileName"/> <br />
fileSize : <bean:write name="fileSize"/> <br />
fileType : <bean:write name="fileType"/>

</body>
</html>
반응형

'Framework > Struts' 카테고리의 다른 글

*.jsp 접근 막기  (0) 2009.09.03
스트러츠(Struts) 기본 세팅  (6) 2009.06.22
//