์๋ฐฉํฅ ๋ฌดํ ์ฐธ์กฐ
JPA๋ฅผ ์ด์ฉํ ๋ ๋ฐ์ํ ์ ์๋ ๋ฌดํ ์ฐธ์กฐ๋ฅผ ์์๋ณด๊ณ ํด๊ฒฐํด๋ณด์.
Post, Reply
๊ฒ์๋ฌผ๊ณผ ๋๊ธ์ ์ํ Entity๊ฐ ์๋ค๊ณ ํด๋ณด์.
package com.vividswan.blog.model;
import java.sql.Timestamp;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import org.hibernate.annotations.CreationTimestamp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment
private int id;
@Column(nullable = false, length = 100)
private String title;
@Lob
private String content;
private int count; // ์กฐํ์
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@OrderBy("id desc")
private List<Reply> replys;
@ManyToOne // Many = Board, One = User
@JoinColumn(name = "userId")
private User user;
@CreationTimestamp
private Timestamp createDate;
}
package com.vividswan.blog.model;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.CreationTimestamp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Reply {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false, length = 200)
private String content;
@ManyToOne
@JoinColumn(name = "boardId")
private Board board;
@ManyToOne
@JoinColumn(name = "userId")
private User user;
@CreationTimestamp
private Timestamp createDate;
public Reply(User user, Board board, String content) {
this.user = user;
this.board = board;
this.content = content;
}
}
Board Model์์ Reply๋ฅผ ๋ถ๋ฅด๋ ๋ถ๋ถ์ ์ดํด๋ณด์.
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@OrderBy("id desc")
private List<Reply> replys;
๋๊ธ์ EAGER
๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ ธ์ค๊ณ OneToMany
์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ๋ก FK๋ก ์ ์ฅ๋์ง ์๋๋ค.
ํ์ง๋ง JPA๋ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ๊ฒ์ํ ์ ๋ณด๋ฅผ ๋ณด๋ด์ค ๋ ๋๊ธ ์ ๋ณด๋ ๊ฐ์ด ๋ณด๋ด์ฃผ๊ฒ ๋๋ค.
Reply Model์์ Reply๋ฅผ ๋ถ๋ฅด๋ ๋ถ๋ถ์ ์ดํด๋ณด์.
@ManyToOne
@JoinColumn(name = "boardId")
private Board board;
ManyToOne
์์ผ๋ก Reply์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ Board์ ๋ํ FK๋ฅผ "boardId"๋ก ๊ฐ๊ณ ์๋ค.
์ด ๋ํ JPA๊ฐ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ๋๊ธ ์ ๋ณด๋ฅผ ๋ณด๋ด์ค ๋ ๊ฒ์ํ ์ ๋ณด๋ ๊ฐ์ด ๋ณด๋ด์ฃผ๊ฒ ๋๋ค.
๋ฌดํ ์ฐธ์ด ๋ฐ์
package com.vividswan.blog.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vividswan.blog.model.Board;
import com.vividswan.blog.repository.BoardRepository;
@RestController
public class InfiniteReferenceTest {
@Autowired BoardRepository boardRepository;
@GetMapping("/test/inReference")
public Board getPost() {
return boardRepository.findById(1).get();
}
}
์์ ๊ฐ๋จํ ํ
์คํธ๋ก ๊ฒ์ํ ์ ๋ณด๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ๋ณด๋ด์ค๋ณด์.
์ด๋, id=1
์ธ ๊ฒ์ํ์ ๋ฏธ๋ฆฌ ์์ฑํ๊ณ , ๊ทธ ๊ฒ์ํ์ ๋๊ธ๋ ๋ฏธ๋ฆฌ ์์ฑํ ๋ค ๋ณด๋ด์ฃผ๋ฉด ๋ฌดํ ์ฐธ์กฐ๋ฅผ ํ์ธํ ์ ์๋ค.
์ด๋ฐ ์ํฉ์ด ๋ฐ์ํ ์ด์ ๋ ์์ Board์ Reply์ ์ฝ๋์์ ํ์ธํ ์ ์๋ค.
JPA์๊ฒ Board ์ ๋ณด๋ฅผ ๋ค๊ณ ์ฌ ๋ Reply ์ ๋ณด๋ ๋ค๊ณ ์๋ฌ๋ผ๊ณ ์์ฒญํ๋ค.
๊ทผ๋ฐ Reply ์ ๋ณด๋ฅผ ๋ค๊ณ ์ฌ ๋ ์ญ์ Board ์ ๋ณด๋ฅผ ๋ค๊ณ ์๋ฌ๋ผ๊ณ ์์ฒญํ๋ค.
๊ทธ๋ ๋ค๋ฉด Board์ ๋ฑ๋ก๋ Reply๋ฅผ ๋ค๊ณ ์ค๋ฉด์ ๋๋ค์ Board๋ฅผ ๋ค๊ณ ์ค๊ณ ์ด๋ ๊ฒ ์๋ก๋ฅผ ๊ณ์ ์ฐธ์กฐํ๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ์ํฉ์ ๋ฌดํ ์ฐธ์กฐ
๋ผ๊ณ ๋งํ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
์ฐ์ ์ด๋ฌํ ๋ฌดํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์ Entitiy ์์ฒด๊ฐ ์๋ DTO๋ฅผ ๋ง๋ค์ด์ ๋ฆฌํดํด์ฃผ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด๋ค.
๋ค๋ฅธ ํด๊ฒฐ ๋ฐฉ๋ฒ๋ค๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ง๋ง ์ฌ๊ธฐ์ JsonIgnoreProperties
๋ฅผ ์ด์ฉํด๋ณด์.
Board Model ๊ฐ์ฒด๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ค.
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JsonIgnoreProperties({"board"})
@OrderBy("id desc")
private List<Reply> replys;
@JsonIgnoreProperties({"board"})
๋ผ๋ ์ด๋
ธํ
์ด์
์ด ์ถ๊ฐ๋ ๊ฑธ ํ์ธํ ์ ์๋ค.
์ด ์ด๋
ธํ
์ด์
์ ์๋ฏธ๋ก๋ board์ ์ํด ํธ์ถ๋ reply์์๋ board ์๋ฃ๋ฅผ ๊ฐ์ ธ์ค์ง ๋ง๋ผ๋ ์ด๋
ธํ
์ด์
์ด๋ค.
๋ ์๊ฐํด ๋ณผ ๊ฑด, board์์ reply์ ์๋ฃ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ์๋ง ํด๋นํ๋ฏ๋ก, ๋ง์ฝ reply๋ง ๋ฐ๋ก ๋ถ๋ฌ์จ๋ค๋ฉด reply์ FK๋ก Board์ ์๋ฃ๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์ด๋ค.
์์ ๊ฐ์ด reply์์ ๋ค์ board์ ์๋ฃ๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ธฐ ๋๋ฌธ์ ๋ฌดํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
'JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA์์ Pageable๋ก ํ์ด์ง ์ฒ๋ฆฌํ๊ธฐ (0) | 2022.03.13 |
---|---|
ORM(Object Relational Mapping) (0) | 2022.03.13 |
JPA ์ํฐํฐ ์ด๋ ธํ ์ด์ (0) | 2022.03.12 |
JPA์์ Optional ์ฒ๋ฆฌ (0) | 2022.03.11 |
Entity ๊ฐ์ ๊ด๊ณ (0) | 2022.03.10 |