๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ“š ์‹œ๋ฆฌ์ฆˆ/- ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA

[๋ฐฐ์›Œ๋ณด์ž Spring Data JPA] ๋งคํ•‘ ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ํ•˜๊ธฐ

by Wonit 2021. 4. 7.

ํ•ด๋‹น ๊ธ€์€ ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA ์‹œ๋ฆฌ์ฆˆ ์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์˜ ๋‚ด์šฉ์ด ์ด์–ด์ง€๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ ๊ธ€์˜ ๋‚ด์šฉ ์ค‘์— ์ƒ๋žต๋˜๋Š” ๋ง๋“ค์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!


ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„๋Š” RDB์— ์žˆ์–ด ์ค‘์š”ํ•œ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

 

์ด๋Ÿฐ ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์™ธ๋ž˜ ํ‚ค์— ๋Œ€ํ•œ ๊ฐœ๋…๊ณผ ๋งคํ•‘ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

 

์™ธ๋ž˜ ํ‚ค์™€ ๋งคํ•‘ ํ…Œ์ด๋ธ”

์™ธ๋ž˜ ํ‚ค๋ž€?

 

๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์™ธ๋ž˜ ํ‚ค๋Š” ํ•œ ํ…Œ์ด๋ธ”์˜ ํ•„๋“œ ์ค‘ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ํ–‰์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ํ‚ค๋ฅผ ๋งํ•œ๋‹ค.

์ด๋Ÿฐ ์™ธ๋ž˜ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์€ ์ฃผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณณ์ผ ๊ฒƒ์ด๋‹ค.

 

์‡ผํ•‘๋ชฐ์—์„œ ์‚ฌ์šฉ์ž์™€ ์ฃผ๋ฌธ ๋ชฉ๋ก์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด์ž.

 

๋งŒ์•ฝ ์‚ฌ์šฉ์ž J๊ฐ€ ์ด ์นซ์†”์„ ๊ตฌ๋งคํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

 

๊ทธ๋Ÿผ ํ…Œ์ด๋ธ”์ด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

 

์ •๊ทœํ™”๋ฅผ ์ž˜ ํ–ˆ๋‹ค๋ฉด ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ตฌ์„ฑํ•  ์ผ์€ ์—†๊ฒ ์ง€๋งŒ ์šฐ์„  ์ด๋ ‡๊ฒŒ ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

 

๊ทธ๋Ÿผ ์‚ฌ์šฉ์ž A๊ฐ€ ์–ด๋–ค ๋ฌผํ’ˆ์„ ์ƒ€๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ์ฟผ๋ฆฌ๋Š” ์•„๋งˆ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

 

SELECT order_item
FROM user
WHERE username = "J"

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ๊ฐ€์ •ํ•ด๋ณด์ž.

 

๋งŒ์•ฝ ์นซ์†”๊ณผ ์น˜์•ฝ์„ ํ•จ๊ป˜ ๊ตฌ๋งคํ–ˆ๋‹ค๋ฉด? ์นซ์†”, ์น˜์•ฝ, ๋น„๋ˆ„, ์ƒดํ‘ธ ๋ฅผ ๊ฐ™์ด ๊ตฌ๋งคํ–ˆ๋‹ค๋ฉด?

 

์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

 

์ง€๊ธˆ DB์—๋Š” Item์„ ์ €์žฅํ•  ๊ณต๊ฐ„์ธ order_item์€ ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ์ƒํƒœ๋ผ ๊ตฌ๋งค๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๊ทธ๋Ÿผ order_item1, order_item2 ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ณ„์† ๋Š˜๋ ค์•ผ ํ•ด์•ผ ํ•˜๋‚˜?

 

์ด๋Ÿด ๋•Œ ๋ฐ”๋กœ ์™ธ๋ž˜ ํ‚ค์™€ ๋งคํ•‘ ํ…Œ์ด๋ธ”์ด ๋“ฑ์žฅํ•œ๋‹ค.

 

๋งคํ•‘ ํ…Œ์ด๋ธ”

๋งคํ•‘ ํ…Œ์ด๋ธ”์€ ๊ฐ ํ…Œ์ด๋ธ”์˜ PK๋ฅผ ์™ธ๋ž˜ ํ‚ค๋กœ ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”๋กœ ๊ฐ’ ์ง‘ํ•ฉ์„ ์ €์žฅํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๋ง์ด ์–ด๋ ต์ง€ ๋ง‰์ƒ ๋ณด๋ฉด ์‰ฝ๋‹ค.

Order_item ํ…Œ์ด๋ธ”

 

Order_Item ํ…Œ์ด๋ธ”์—์„œ๋Š” item_id์™€ user_Id ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

 

์ด๋Ÿฐ ์‹์œผ๋กœ ํ…Œ์ด๋ธ”์„ ๋‚˜๋ˆˆ๋‹ค๋ฉด ์–ด๋–ค ์ด์ ์ด ์žˆ์„๊นŒ?

 

- user_id๋Š” User ํ…Œ์ด๋ธ”์˜ PK๋กœ ์‹๋ณ„ํ•˜๋Š” ์™ธ๋ž˜ํ‚ค๋กœ order_item ์ด ์–ด๋–ค ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ตฌ๋งค๋˜์—ˆ๋Š”์ง€๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๊ณ ,

- item_id๋Š” Item ํ…Œ์ด๋ธ”์˜ PK๋กœ ์‹๋ณ„ํ•˜๋Š” ์™ธ๋ž˜ํ‚ค๋กœ order_item์ด ์–ด๋–ค ์•„์ดํ…œ์„ ๊ฐ–๋Š”์ง€๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋Ÿผ ์œ„์—์„œ ๋ง ํ•˜๋Š” ๋ฌธ์ œ, ๋งŒ์•ฝ์นซ์†”๊ณผ ์น˜์•ฝ์„ ํ•จ๊ป˜ ๊ตฌ๋งคํ–ˆ๋‹ค๋ฉด? ์นซ์†”, ์น˜์•ฝ, ๋น„๋ˆ„, ์ƒดํ‘ธ ๋ฅผ ๊ฐ™์ด ๊ตฌ๋งคํ–ˆ๋‹ค๋ฉด? ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์–ด๋–ป๊ฒŒ?

 

item์ด ๋Š˜์–ด๋‚  ์ˆ˜๋ก Order_Item ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๊ณ , SELECT ํ•  ๋•Œ, user_id ๊ฐ€ ํŠน์ • ํšŒ์›์ธ ๋กœ์šฐ๋งŒ ์žก์•„์˜ค๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์—!

ํ…Œ์ด๋ธ” ์—ฐ๊ด€ ๊ด€๊ณ„

๊ทธ๋Ÿผ ๋‚ด์นœ๊น€์— ์ชผ๊ธˆ๋งŒ ๋” ์ƒ๊ฐํ•ด๋ณด์ž.

 

์ด๋Ÿฌํ•œ ๋งคํ•‘ ํ…Œ์ด๋ธ”์—๋Š” ๊ด€๊ณ„๊ฐ€ ์•„์ฃผ ์ค‘์š”ํ•œ ์กด์žฌ์ธ๋ฐ, ๊ด€๊ณ„๋ž€ ์ผ๋ฐ˜ ํ…Œ์ด๋ธ”๊ณผ *_๋งคํ•‘ ํ…Œ์ด๋ธ”์ด ์–ด๋–ค *_ํ˜•ํƒœ๋กœ ์—ฐ๊ฒฐ๋˜์—ˆ๋Š”์ง€๋ฅผ ๋œปํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

  • User ํ…Œ์ด๋ธ” ์ž…์žฅ์—์„œ ํ•œ ๋ช…์˜ User๋Š” ์—ฌ๋Ÿฌ Order_Item์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • Item ํ…Œ์ด๋ธ” ์ž…์žฅ์—์„œ ํ•˜๋‚˜์˜ Item์€ ์—ฌ๋Ÿฌ Order_item์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด ๊ฒƒ๋“ค์„ ํ…Œ์ด๋ธ” ์—ฐ๊ด€ ๊ด€๊ณ„๋ผ๊ณ  ํ‘œํ˜„ํ•˜๊ณ , ์ด ๊ด€๊ณ„๋ฅผ ํฌ๊ฒŒ 3๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

 

  1. 1:1
  2. 1:N
  3. N:1

์›๋ž˜ N:M ๊ด€๊ณ„๋„ ์กด์žฌํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋ฏ€๋กœ ์ƒ๋žตํ•œ๋‹ค.

๋‹ค์‹œ Java๋กœ ๋Œ์•„์™€์„œ ์ƒ๊ฐํ•ด๋ณด์ž.

์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ ๊ฐ์ฒด์ง€ํ–ฅ ํŒจ๋Ÿฌ๋‹ค์ž„์—์„œ SQL ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ด์šฉํ•˜๋ ค๊ณ  ํ•˜๊ณ  ์žˆ๋‹ค.

 

์ด๋Š” ์ „์— ๋ง ํ–ˆ๋˜ ํŒจ๋Ÿฌ๋‹ค์ž„, ์ž„ํ”ผ๋˜์Šค ๋ถˆ์ผ์น˜์˜ ๋ฌธ์ œ๋ฅผ ์•ˆ๊ณ  ์žˆ๋Š” ๊ฒƒ์ธ๋ฐ, ๊ถ๊ทน์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฆ‰, ์ด๋Ÿฌํ•œ SQL ์ฟผ๋ฆฌ๋ฅผ

 

SELECT name
FROM item I
    JOIN order_item OI ON U.id = I.id
WHERE OI.user_id = 10;

์ด๋Ÿฌํ•œ ์ž๋ฐ”์˜ ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ์€ ๊ฒƒ์ด๋‹ค.

 

์ด๋ฅผ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

 

OrderItem orderItem = user.getOrderItem();
Item item = orderItem.getItem();

item.getName();

์—ฐ๊ด€๊ด€๊ณ„ ์–ด๋…ธํ…Œ์ด์…˜

์ด๋Ÿฐ ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ JPA ์—์„œ ํ˜น์€ ์ž๋ฐ”์—์„œ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ ์–ด๋…ธํ…Œ์ด์…˜์„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

 

  1. @OneToOne : ์ผ๋Œ€์ผ ๋งคํ•‘
  2. @OneToMany : ์ผ๋Œ€๋‹ค ๋งคํ•‘ (์‚ฌ์šฉ์ž, 1) : (์ฃผ๋ฌธ ๋ชฉ๋ก, N)
  3. @ManyToOne : ๋‹ค๋Œ€์ผ ๋งคํ•‘ (์ฃผ๋ฌธ ๋ชฉ๋ก, N) : (์‚ฌ์šฉ์ž, 1)

์‹ค์ œ ์ฝ”๋“œ๋กœ ๋จผ์ € ๋ด๋ณด์ž.

OrderItem ํด๋ž˜์Šค

@Entity
public class OrderItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY) // 1
    @JoinColumn(name = "userId") // 2
    private User userId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "itemId")
    private Item itemId;
}

User ํด๋ž˜์Šค

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;

    @OneToMany(mappedBy = "user")
    private List<OrderItem> orderItems = new ArrayList<>();
}

Item ํด๋ž˜์Šค๋„ List<> ๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•˜๋Š”๊ฒŒ ์•„๋‹Œ๊ฐ€? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค ๋•Œ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ•œ ๋ฒˆ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋œ๋‹ค.
Item ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ค ์ฃผ๋ฌธ์ด ๋˜์—ˆ๋Š”์ง€ ์•Œ์•„์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ?

 

์ง€๋‚œ ์‹œ๊ฐ„์— ํ™•์ธํ–ˆ๋˜ ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘์—์„œ ๋ณด์ง€ ๋ชปํ–ˆ๋˜ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์ด ์กด์žฌํ•œ๋‹ค.

 

  • @ManyToOne(fetch = FetchType.LAZY)
  • @JoinColumn(name = "")
  • @OneToMany(mappedBy = "")

@ManyToOne, ๋‹ค๋Œ€์ผ ๋งคํ•‘

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ๋‹ค๋Œ€์ผ ๊ด€๊ณ„์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

OrderItem ์ž…์žฅ์—์„œ๋Š” ํ•˜๋‚˜์˜ ์•„์ดํ…œ์€ ํ•œ ๋ช…์˜ User ์—๊ฒŒ ๋งคํ•‘๋˜์–ด์•ผ ํ•˜๊ณ 
๊ทธ๋Ÿผ (OrderItem) ๋‹ค : ์ผ (User) ์˜ ๊ด€๊ณ„๊ฐ€ ์„ฑ๋ฆฝํ•œ๋‹ค.

๋ณดํ†ต ์ฐธ์กฐ ํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ ์—์„œ ์‚ฌ์šฉ์„ ํ•˜๋Š”๋ฐ, ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํŽธํ•˜๋‹ค.

 

@ManyToOne ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ๋ณด๋ฉด ๋’ค์— fetch = FetchType.LAZY ๊ฐ€ ๋ถ™์–ด์žˆ๋‹ค.

 

FetchType

FetchType ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” JPA ํ”„๋ก์‹œ๋ผ๋Š” ๊ฐœ๋…์„ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

 

ํ˜„์žฌ ๋ชฉ์ ์€ JPA๋ฅผ ๋ถ„์„ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋‹จ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๊ณ , ๋‘ ๊ฐ€์ง€๋งŒ ๊ธฐ์–ตํ•˜์ž.

  • ์ฆ‰์‹œ ๋กœ๋”ฉ (FecthType.EAGER)
    • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฆ‰์‹œ ํ•œ ๋ฒˆ์— ์กฐํšŒํ•œ๋‹ค.
    • ์ฆ‰, ์‹ค์ œ ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋”๋ผ๋„ ์กฐํšŒ๋ฅผ ํ•ด์˜จ๋‹ค.
  • ์ง€์—ฐ ๋กœ๋”ฉ (FetchType.LAZY)
    • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ์‹ค์ œ ์‚ฌ์šฉ ์‹œ์ ์— ์กฐํšŒํ•œ๋‹ค.
    • ์ฆ‰, ์‹ค์ œ ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ์‹œ์ ๊นŒ์ง€ ์กฐํšŒ๋ฅผ ๋ฏธ๋ฃฌ๋‹ค.

 

๊ฐ€๊ธ‰์ ์ด๋ฉด FetchType.LAZY ๋ฅผ ๊ถŽ์žฅํ•œ๋‹ค.

@OneToMany, ์ผ๋Œ€๋‹ค ๋งคํ•‘

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„ ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

, User ์ž…์žฅ์—์„œ ํ•˜๋‚˜์˜ ์‚ฌ์šฉ์ž๋Š” ์—ฌ๋Ÿฌ ์ฃผ๋ฌธ ์•„์ดํ…œ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿผ (User) ์ผ : ๋‹ค (OrderItem) ์˜ ๊ด€๊ณ„๊ฐ€ ์„ฑ๋ฆฝํ•œ๋‹ค.

๋ณดํ†ต ์ฐธ์กฐ ๋‹นํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ ์—์„œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, List ์ปฌ๋ ‰์…˜์„ ์ฐธ์กฐ๋ณ€์ˆ˜๋กœ ํ•œ๋‹ค.

@OneToMany ์–ด๋…ธํ…Œ์ด์…˜์— ๋ณด๋ฉด ๋’ค์— mappedBy = "" ๊ฐ€ ๋ถ™์–ด์žˆ๋‹ค.

mappedBy

mappedBy๋Š” ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ๋…์ด๋‹ค.

 

์–‘๋ฐฉํ–ฅ์œผ๋กœ ์ฐธ์กฐ๋  ๋•Œ ์ฐธ์กฐ ๋‹นํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

ํ˜•์‹์€ @OneToMany(mappedBy = "์ฐธ์กฐํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ์— ์žˆ๋Š” ๋ณ€์ˆ˜ ์ด๋ฆ„") ์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

mappedBy๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”, ํ˜„์žฌ ์ž์‹ ์˜ ์ฐธ์กฐ๊ฐ€ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์— ์–ด๋–ค ๋ณ€์ˆ˜๋กœ ์ง€์ •๋˜์—ˆ๋Š”์ง€ JPA ์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•จ ์ฏค์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ž.

 

์–‘๋ฐฉํ–ฅ๊ณผ ๋‹จ๋ฐฉํ–ฅ

@ManyToOne ๋งŒ ์กด์žฌํ•œ๋‹ค๋ฉด, ์ฆ‰ OrderItem ํด๋ž˜์Šค๋งŒ User์˜ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด, ์ด๋Š” ๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋ผ๊ณ  ํ•œ๋‹ค.

 

๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ๋ด๋„, ๊ด€์‹ฌ์‚ฌ๋กœ ๋ด๋„ ํ›จ์”ฌ ์ด๋“์ด ๋งŽ๋‹ค.

 

๊ทธ๋ž˜๋„ ์šฐ๋ฆฌ๋Š” ์–‘๋ฐฉํ–ฅ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์–ด์ฉ” ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ๋“ค์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋Ÿผ ๋‹ค์Œ์„ ๊ธฐ์–ตํ•˜์ž

 

  • ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๋  ๋•Œ _์™ธ๋ž˜ ํ‚ค_๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์„ ์ฃผ์ฒด๋ฅผ ํ™•์‹คํžˆ ํ•  ๊ฒƒ
    • ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ฐ–๋Š” ์ฃผ์ฒด๋Š” DB ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์žˆ๋Š” ์ชฝ์œผ๋กœ ํ•œ๋‹ค.
    • ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ฐ–๋Š” ์ชฝ์—์„œ๋งŒ UPDATE์™€ INSERT ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ์—†๋Š” ์ชฝ์€ SELECT ๋งŒ ์ˆ˜ํ–‰ํ•  ๊ฒƒ
  • ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„์—์„œ ์ƒํ˜ธ ์ฐธ์กฐ๋ฅผ ์ฃผ์˜ํ•  ๊ฒƒ
    • Lombok ์˜ @ToString
      • @ToString(exclude = "") ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๊ฒฐ
    • MVC ์—์„œ JSON Converting ๋  ๋•Œ
      • ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ†ต์‹ ์—์„œ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  DTO ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•  ๊ฒƒ

ํ…Œ์ŠคํŠธ

์—ฌ๊ธฐ ๊นŒ์ง€ ์ž˜ ๋˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ง€๋‚œ ์‹œ๊ฐ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ„์˜ ๊ฐœ๋…๋“ค์„ ์ฝ”๋“œ๋กœ ์ฆ๋ช…ํ•ด๋ณด์ž.

 

์šฐ๋ฆฌ๊ฐ€ ์ฆ๋ช…ํ•  ๊ฒƒ์€, ํ•˜๋‚˜์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ ์•„์ดํ…œ์„ ๊ฐ€์กŒ์„ ๋•Œ, ํ•ด๋‹น ์ฃผ๋ฌธ ๋ชฉ๋ก์—์„œ ์ฃผ๋ฌธํ•œ ์‚ฌ์šฉ์ž ์ด๋ฆ„์ด ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„๊ณผ ๋™์ผํ•œ์ง€๋ฅผ ํ…Œ์ŠคํŠธํ•  ๊ฒƒ์ด๋‹ค.

 

  • Entity
    • User.class
    • Item.class
    • OrderItem.class
  • Repository
    • UserRepository.interface
    • ItemRepository.interface
    • OrderItemRepository.interface
  • Test
    • OrderItemRepository.class

์˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

User, Item, OrderItem


@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder @Getter
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;

    @OneToMany(mappedBy = "user")
    private List<OrderItem> orderItems = new ArrayList<>();
}

// ์–ด๋…ธํ…Œ์ด์…˜ ์ƒ๋žต
public class Item {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

// ์–ด๋…ธํ…Œ์ด์…˜ ์ƒ๋žต
public class OrderItem {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "item_id")
    private Item item;
}

UserRepository, ItemRepository, OrderItemRepository

public interface UserRepository extends JpaRepository<User, Long> {}
public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {}
public interface ItemRepository extends JpaRepository<Item, Long> {}

OrderItemRepository

@SpringBootTest
@Transactional
@Rollback(false)
class OrderItemRepositoryTest {

    @Autowired ItemRepository itemRepository;
    @Autowired UserRepository userRepository;
    @Autowired OrderItemRepository orderItemRepository;

    @Test
    void createTest() {

        // given
        String username = "James";
        User user = User.builder()
                .username(username)
                .build();

        userRepository.save(user);

        List<OrderItem> orderItems = new ArrayList<>();

        for (int i = 1; i <= 2; i++) {
            Item item = itemRepository.save(Item.builder()
                    .name("item " + i)
                    .build());
            OrderItem orderItem = OrderItem.builder()
                    .item(item)
                    .user(user)
                    .build();

            orderItems.add(orderItem);
        }

        // when
        List<OrderItem> savedOrderItems = orderItemRepository.saveAll(orderItems);

        //then
        assertEquals(username, savedOrderItems.get(0).getUser().getUsername());
        assertEquals(username, savedOrderItems.get(1).getUser().getUsername());
    }

}

 

์—ฌ๊ธฐ์„œ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ์ƒ๋‹จ์— @Transactional๊ณผ @Rollback ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ญ˜๊นŒ?

 

  • @Trasacntional
    • JPA์˜ ๋ชจ๋“  ์ž‘์—…์€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ผ์–ด๋‚˜๊ฒŒ ๋œ๋‹ค.
    • ํ•ด๋‹น ํด๋ž˜์Šค์˜ ํŠธ๋žœ์žญ์…˜ ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ๊ฑธ์–ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.
  • @Rollback
    • ํŠธ๋žœ์žญ์…˜์˜ Rollback ๊ฐœ๋…๊ณผ ๋™์ผํ•˜๋‹ค.
    • false ๋กœ ์„ค์ •ํ•œ๋‹ค๋ฉด ์‹คํ–‰ ์‹œ์— DB์— ์ €์žฅํ•œ๋‹ค. : rollback ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • true ๋กœ ์„ค์ •ํ•œ๋‹ค๋ฉด ์‹คํ–‰ ์‹œ์— DB์— ์ €์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค. : rollback์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

ํŠธ๋žœ์žญ์…˜๊ณผ Rollback์— ๋Œ€ํ•ด์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ด๋ก 
Transaction, ํŠธ๋žœ์žญ์…˜ ์ด๋ž€? ๊ณผ Isolation Level, ๊ณ ๋ฆฝ ์ˆ˜์ค€์ด๋ž€? ์„ ์ฐธ๊ณ ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋Œ“๊ธ€