πŸ“š μ‹œλ¦¬μ¦ˆ/- λ°°μ›Œλ³΄μž Spring Data JPA

[λ°°μ›Œλ³΄μž Spring Data JPA] λ§€ν•‘ ν…Œμ΄λΈ”κ³Ό 연관관계 λ§€ν•‘ν•˜κΈ°

Wonit 2021. 4. 7. 23:00

ν•΄λ‹Ή 글은 λ°°μ›Œλ³΄μž 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, 고립 μˆ˜μ€€μ΄λž€? 을 μ°Έκ³ ν•˜λŠ” 것도 쒋을 것 κ°™λ‹€.