๐[Spring] ์๋ฐฉํฅ ๊ด๊ณ๋ ๋ฌด์์ผ๊น์?
-
์๋ฐฉํฅ ๊ด๊ณ๋ ๋ ์ํฐํฐ๊ฐ ์๋ก๋ฅผ ์ฐธ์กฐํ ์ ์๋ ๊ด๊ณ๋ฅผ ์๋ฏธํฉ๋๋ค.
- ์ฆ, ํ ์ํฐํฐ์์ ๋ค๋ฅธ ์ํฐํฐ๋ฅผ ์ฐธ์กฐํ ์ ์์ ๋ฟ๋ง ์๋๋ผ, ๋ฐ๋๋ก ๋ค๋ฅธ ์ํฐํฐ์์๋ ์ด๋ฅผ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
- ์๋ฐฉํฅ ๊ด๊ณ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์ํฐํฐ ๊ฐ์ ๋ฐ์ดํฐ ํ์์ด ์์ชฝ ๋ฐฉํฅ์ผ๋ก ๋ชจ๋ ๊ฐ๋ฅํด์ง๋ฉฐ, ์ด๋ JPA์์ ๋ค์๊ณผ ๊ฐ์ ๊ด๊ณ ์ด๋
ธํ
์ด์
์กฐํฉ์ผ๋ก ๊ตฌํ๋ฉ๋๋ค.
-
@OneToMany
+@ManyToOne
-
@OneToOne
+@OneToOne
-
@ManyToMany
+@ManyToMany
-
1๏ธโฃ ์๋ฐฉํฅ ๊ด๊ณ์ ํน์ง.
1๏ธโฃ ์์ชฝ์์ ์ฐธ์กฐ ๊ฐ๋ฅ.
- ์์ชฝ ์ํฐํฐ๊ฐ ์๋ก๋ฅผ ์ฐธ์กฐํ์ฌ ๋ฐ์ดํฐ ํ์์ด ๊ฐ๋ฅํฉ๋๋ค.
- ์๋ฅผ ๋ค์ด, ๋ถ๋ชจ ์ํฐํฐ์์ ์์ ์ํฐํฐ๋ค์ ์กฐํํ๊ฑฐ๋, ์์ ์ํฐํฐ์์ ๋ถ๋ชจ ์ํฐํฐ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
2๏ธโฃ ์ฃผ์ธ(Owner)๊ณผ ๋น์ฃผ์ธ(Inverse) ์ค์ .
- JPA์์ ์๋ฐฉํฅ ๊ด๊ณ๋ฅผ ์ค์ ํ ๋, ๋ฐ๋์ ์ฃผ์ธ(Owner)๊ณผ ๋น์ฃผ์ธ(Inverse)์ ๋ช ์ํด์ผ ํฉ๋๋ค.
- ์ฃผ์ธ(Owner) : ์ธ๋ ํค(Foreign Key)๋ฅผ ์ค์ ๋ก ๊ด๋ฆฌํ๋ ์ชฝ.
-
๋น์ฃผ์ธ(Inverse) : ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ฐธ์กฐ๋ง ๊ฐ๋ฅํ๋ฉฐ,
mappedBy
์์ฑ์ ํตํด ์ฃผ์ธ์ ๋ช ์ํฉ๋๋ค.
3๏ธโฃ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ธ๋ ํค๋ ํ์ชฝ์๋ง ์กด์ฌ.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ๋ ํค(Foreign Key)๋ ๊ด๊ณ์ ์ฃผ์ธ์ ํด๋นํ๋ ์ํฐํฐ์ ํ ์ด๋ธ์๋ง ์กด์ฌํฉ๋๋ค.
2๏ธโฃ ์๋ฐฉํฅ ๊ด๊ณ์ ๊ตฌํ ํํ.
1๏ธโฃ @OneToMany
+ @ManyToOne
- ๋ถ๋ชจ-์์ ๊ด๊ณ๋ฅผ ๊ตฌํํ๋ฉฐ, ๋ถ๋ชจ๋ ์์์ ์ปฌ๋ ์ ์ ๊ฐ์ง๊ณ ์๊ณ , ์์์ ๋ถ๋ชจ๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์์ : User์ UserSaveHistory
- User ์ํฐํฐ(๋ถ๋ชจ)
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<UserSaveHistory> saveHistories = new ArrayList<>(); public void addSaveHistory(UserSaveHistory history) { saveHistories.add(history); history.setUser(this); } public void removeSaveHistory(UserSaveHistory history) { saveHistories.remove(history); history.setUser(null); } }
- UserSaveHistory ์ํฐํฐ(์์)
@Entity public class UserSaveHistory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; }
2๏ธโฃ @OneToOne
+ @OneToOne
- 1:1 ๊ด๊ณ๋ฅผ ๊ตฌํํ๋ฉฐ, ์์ชฝ ์ํฐํฐ๊ฐ ์๋ก๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์์ : Passport์ Person
- Person ์ํฐํฐ.
@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(mappedBy = "person", cascade = CascadeType.ALL) private Passport passport; }
- Passport ์ํฐํฐ.
@Entity public class Passport { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne @JoinColumn(name = "person_id") private Person person; }
3๏ธโฃ @ManyToMany
+ @ManyToMany
- ๋ค๋๋ค ๊ด๊ณ๋ฅผ ๊ตฌํํ๋ฉฐ, ์ค๊ฐ ํ ์ด๋ธ์ ํตํด ๋ ์ํฐํฐ๊ฐ ์ฐ๊ฒฐ๋ฉ๋๋ค.
์์ : Student์ Course
- Student ์ํฐํฐ.
@Entity public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private List<Course> courses = new ArrayList<>(); }
- Course ์ํฐํฐ.
@Entity public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToMany(mappedBy = "courses") private List<Student> students = new ArrayList<>(); }
3๏ธโฃ ์๋ฐฉํฅ ๊ด๊ณ์์ ์ฃผ์์ .
1๏ธโฃ ์ฃผ์ธ(Owner)๊ณผ ๋น์ฃผ์ธ(Inverse)
- JPA์์๋ ์๋ฐฉํฅ ๊ด๊ณ๋ฅผ ์ค์ ํ ๋ ๋ฐ๋์ ์ฃผ์ธ์ ๋ช ์ํด์ผ ํฉ๋๋ค.
- ์ฃผ์ธ์ ์ธ๋ ํค(Foreign Key)๋ฅผ ๊ด๋ฆฌํ๋ฉฐ, ๋ฐ์ดํฐ ๋ณ๊ฒฝ(INSERT, UPDATE)์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
-
๋น์ฃผ์ธ์
mappedBy
์์ฑ์ ์ฌ์ฉํด ์ฃผ์ธ์ ์ง์ ํ๋ฉฐ, ์ฝ๊ธฐ ์ ์ฉ์ ๋๋ค.
2๏ธโฃ ์ฐ๊ด ๊ด๊ณ ํธ์ ๋ฉ์๋.
- ๋ถ๋ชจ์ ์์ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ผ๊ด๋๊ฒ ์ ์งํ๋ ค๋ฉด ํธ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
- ์๋ฅผ ๋ค์ด, ๋ถ๋ชจ์
addChild
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์์์ ๋ถ๋ชจ๋ ์๋์ผ๋ก ์ค์ ๋๋๋ก ๊ตฌํํฉ๋๋ค.public void addSaveHistory(UserSaveHistory history) { saveHistories.add(history); history.setUser(this); }
- ์๋ฅผ ๋ค์ด, ๋ถ๋ชจ์
๐โโ๏ธ ํธ์ ๋ฉ์๋
๊ด๊ณ๋ฅผ ๋๊ธฐํํ๊ธฐ ์ํ ํธ์ ๋ฉ์๋๋ ์๋ฐฉํฅ ์ฐ๊ด ๊ด๊ณ์์ ๋ ์ํฐํฐ ๊ฐ์ ์ฐ๊ด ๊ด๊ณ๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฉ์๋๋ฅผ ์๋ฏธํฉ๋๋ค.
3๏ธโฃ ์ง์ฐ ๋ก๋ฉ(Lazy Loading)
- ์๋ฐฉํฅ ๊ด๊ณ์์๋
@OneToMany
์@ManyToOne
๋ชจ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ฐ ๋ก๋ฉ(Lazy Loading)์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค. - ํ์์
fetch = FetchType.EAGER
๋ก ์ค์ ํ ์ ์์ง๋ง, ์ด๋ ๋ฐ์ดํฐ ๋ก๋ฉ ์ ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
4๏ธโฃ ๋ฌดํ ๋ฃจํ ๋ฌธ์
- ์๋ฐฉํฅ ๊ด๊ณ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํ ๋, ๋ถ๋ชจ์ ์์์ด ์๋ก๋ฅผ ์ฐธ์กฐํ๋ฉฐ ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ํด๊ฒฐ ๋ฐฉ๋ฒ
-
@JsonIgnore
: ํน์ ํ๋๋ฅผ ์ง๋ ฌํํ์ง ์๋๋ก ์ค์ . -
@JsonManagedReference
์@JsonBackReference
: Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ด๊ณ๋ฅผ ์ฒ๋ฆฌํ๋ ์ด๋ ธํ ์ด์ .
-
- ํด๊ฒฐ ๋ฐฉ๋ฒ
4๏ธโฃ ์ฅ์ ๊ณผ ๋จ์ .
1๏ธโฃ ์ฅ์ .
1๏ธโฃ ์์ชฝ ํ์ ๊ธฐ๋ฅ.
- ๋ถ๋ชจ์ ์์ ๋ชจ๋์์ ๊ด๊ณ๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
2๏ธโฃ ๋ช ํํ ๊ด๊ณ ํํ.
- ๊ฐ์ฒด ๋ชจ๋ธ์์ ๋ ์ํฐํฐ ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ช ํํ๊ฒ ํํํ ์ ์์ต๋๋ค.
2๏ธโฃ ๋จ์ .
1๏ธโฃ ์ค๊ณ ๋ณต์ก์ฑ ์ฆ๊ฐ.
- ๊ด๊ณ๋ฅผ ์์ชฝ์์ ๊ด๋ฆฌํด์ผ ํ๋ฏ๋ก ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์์ต๋๋ค.
2๏ธโฃ ์ฑ๋ฅ ๋ฌธ์ .
- ์๋ฐฉํฅ ๊ด๊ณ๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ถํ์ํ ๋ฐ์ดํฐ ๋ก๋ฉ์ด ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ๋ก๋ฉ ์ ๋ต์ ์ ์คํ ์ ํํด์ผ ํฉ๋๋ค.
5๏ธโฃ ๊ฒฐ๋ก .
- ์๋ฐฉํฅ ๊ด๊ณ๋ ๋ ์ํฐํฐ ๊ฐ์ ์ํธ ์ฐธ์กฐ๊ฐ ํ์ํ ๋ ์ฌ์ฉ๋๋ฉฐ, ์ค๊ณ๊ฐ ๋ณต์กํด์ง ์ ์์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์์ชฝ ๋ฐฉํฅ์ผ๋ก ํ์ํด์ผ ํ๋ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค.
- JPA์์๋ ์ฃผ์ธ(Owner)์ ๋ช ํํ ์ค์ ํ๊ณ , ํธ์ ๋ฉ์๋๋ฅผ ํตํด ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํจ์ผ๋ก์จ ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ ์ ์งํด์ผ ํฉ๋๋ค.
- ํ์ ์๋ ๊ฒฝ์ฐ ๋จ๋ฐฉํฅ ๊ด๊ณ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ฐ๋จํ๊ณ ์ฑ๋ฅ์ ์ ๋ฆฌํฉ๋๋ค.