Weekly TIL - Day 30

2025. 5. 14. 09:54·Weekly TIL

⭐️ Today's summary

오늘은 ORM 연관 맵핑에 대해 배웠다. 이 연관 관계를 맵핑하면서 엔티티 설계를 단방향 관계로 할지,

양방향 관계로 할지 중요하였다.

 

오늘은 그 부분에 대해서 다뤄보겠다.

 

⭐️ Problem

우선 엔티티 설계 하는것이 어려워서 엔티티 설계를 숙제로 내주셨는데, 아래에 엔티티 설계를 해보겠다.

 

⭐️ Try

[ Member.java ]

package com.kh.jpa.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Member {
    @Id
    @Column(name = "user_id", length = 30)
    private String userId;

    @Column(nullable = false, length = 100, name = "user_pwd")
    private String userPw;

    @Column(nullable = false, length = 15, name = "user_name")
    private String userName;

    private String email;

    @Check(constraints = "gender IN ('M', 'F')")
    @Column(length = 1)
    private String gender;

    private int age;

    @Column(length = 13)
    private String phone;

    @Column(length = 100)
    private String address;

    @CreationTimestamp
    @Column(name = "enroll_date", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
    private LocalDateTime enrollDate;

    @UpdateTimestamp
    @Column(name = "modify_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
    private LocalDateTime modifyDate;

    @Column(length = 1, nullable = false, columnDefinition = "varchar(1) default 'Y'")
    @Check(constraints = "status IN ('Y', 'M')")
    private String status;

    @OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
    private List<Notice> noticeList = new ArrayList<>();



}

 

우선 엔티티 설정, 테이블명 설정, PK설정, 컬럼명 설정 등 해보았다.

 

그리고 양방향 설계는 아직 어떤것을 양방향으로 설계해야할지 몰라서 하나만 넣어보았다.

 

양방향 설계는 저기에 나와있듯이 Member엔티티가 Notice엔티티를 조회할 필요가 있을 때 사용하면 될거같다.

 


 

[ Profile.java ]

package com.kh.jpa.entity;


import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Profile {
    @Id
    @Column(length = 30, name = "user_id")
    private String userId;

    @Column(name = "profile_image", length = 100)
    private String profileImage;

    @Column(length = 300)
    private String intro;

    // 외래키
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @MapsId
    @JoinColumn(name = "user_id", nullable = false)
    private Member member;

}

 

여기에선 외래키 설정을 해주었다. 외래키는 @JoinColumn을 이용하여 name="~~" 에 나오는 컬럼을 FK로 만들겠다는 말이다.

 

여기선 기본키와 외래키이며, 1:1 관계이다.

 

또한 @MapsId를 사용한 이유는 "이 필드는 외래키이자 기본키로 사용한다"라는 것을 JPA에게 알려준다.

 

즉, Profile.userId는 Member.userId와 동일한 값을 가지게 된다.

 


 

[ Notice.java ]

package com.kh.jpa.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Notice {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "notice_no")
    private Long noticeNo;

    @Column(name = "notice_title", nullable = false, length = 30)
    private String noticeTitle;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "notice_writer", nullable = false, columnDefinition = "VARCHAR(30)")
    private Member member;

    @Column(name = "notice_content", length = 200, nullable = false)
    private String noticeContent;

    @CreationTimestamp
    @Column(name = "create_date", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
    private LocalDateTime createDate;


}

 

여기선 @JoinColumn을 쓰게되면 외래키로 등록이되지만 타입을 주고싶은데 타입이 객체 타입이기때문에,

 

기본값으로 columnDefinition = "VARCHAR(30)"  이런식으로 타입을 줄 수 있다.

 


 

[ Board.java ]

package com.kh.jpa.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "board_no")
    private long boardNo;

    @Column(name = "board_title", nullable = false, length = 100)
    private String boardTitle;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "board_writer", columnDefinition = "VARCHAR(30)")
    private Member member;

    @Column(name = "board_content", nullable = false, columnDefinition = "CLOB")
    private String boardContent;

    @Column(name = "origin_name", length = 100)
    private String originName;

    @Column(name = "change_name", length = 100)
    private String changeName;

    @Column(columnDefinition = "int default 0")
    private int count;

    @CreationTimestamp
    @Column(name = "create_date", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
    private LocalDateTime createDate;

    @Column(length = 1, nullable = false, columnDefinition = "varchar(1) default 'Y'")
    @Check(constraints = "status IN ('Y', 'M')")
    private String status;

}

 

@Check 어노테이션을 사용하여 check 제약조건을 추가해 주었다.

 


 

[ Reply.java ]

package com.kh.jpa.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Reply {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "reply_no")
    private long replyNo;

    @Column(name = "reply_content", length = 400, nullable = false)
    private String replyContent;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "ref_bno", columnDefinition = "int", nullable = false)
    private Board board;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "reply_writer", columnDefinition = "varchar(30)", nullable = false)
    private Member member;


    @CreationTimestamp
    @Column(name = "create_date", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", nullable = false)
    private LocalDateTime createDate;

    @Column(length = 1, nullable = false, columnDefinition = "varchar(1) default 'Y'")
    @Check(constraints = "status IN ('Y', 'M')")
    private String status;
}

 

Reply 엔티티에선 외래키가 두개이기때문에 두개의 연관관계를 지어보았다.

 


 

[ Tag.java ]

package com.kh.jpa.entity;


import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Tag {
    @Id
    @Column(name = "tag_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long tagId;

    @Column(name = "tag_name", length = 30, nullable = false, unique = true)
    private String tagName;

}

 


 

[ BoardTage.java ]

package com.kh.jpa.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "BOARD_TAG")
public class BoardTag {
    @Id
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "BOARD_NO", nullable = false, columnDefinition = "int")
    private Board board;

    @Id
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "TAG_ID", nullable = false, columnDefinition = "int")
    private Tag tag;

}

 

마지막으로 여기선 Board_ID와 TAG_ID가 기본키이면서 외래키이기때문에 위와같이 설정해보았다.

 

 

엔티티설계를 처음 해보았는데, 여러번 해보다보면 익숙해 지고, 객체 지향 설계를 할 수 있어서 좋을 것 같다.

'Weekly TIL' 카테고리의 다른 글

Weekly TIL - Day 32  (2) 2025.05.16
Weekly TIL - Day 31  (2) 2025.05.15
Weekly TIL - Day 29  (0) 2025.05.13
Weekly TIL - Day 28  (0) 2025.05.12
Code Review (Weekly TIL - Day 27)  (2) 2025.05.11
'Weekly TIL' 카테고리의 다른 글
  • Weekly TIL - Day 32
  • Weekly TIL - Day 31
  • Weekly TIL - Day 29
  • Weekly TIL - Day 28
KoesJin
KoesJin
hEELo
  • KoesJin
    Seok DevLog
    KoesJin
  • 전체
    오늘
    어제
    • 분류 전체보기 (109)
      • Back End (31)
        • DataBase (15)
        • JAVA (12)
        • JDBC (4)
      • Front End (9)
        • HTML5 & CSS (3)
        • Java Script (6)
        • REACT (0)
      • Server (9)
        • JSP - TomCat - Servlet (7)
        • Spring Boot (2)
      • GitHub (1)
      • IT 지식 (기술면접 대비) (20)
      • Weekly TIL (39)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    commit
    GC
    weekly til - day 38
    DAO
    weekly til - day 39
    order by
    css
    weekly til - day 43
    순서에 대하여
    weekly til - day 41
    INNER JOIN
    dml
    where
    DDL
    exception
    from
    MVC 패턴
    View
    weekly til - day 40
    select
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
KoesJin
Weekly TIL - Day 30
상단으로

티스토리툴바