ํด๋น ๊ธ์ ๋ฐฐ์๋ณด์ Spring Data JPA ์๋ฆฌ์ฆ ์ ๋๋ค.
ํด๋น ์๋ฆฌ์ฆ์ ๋ด์ฉ์ด ์ด์ด์ง๋ ํํ์ด๋ฏ๋ก ๊ธ์ ๋ด์ฉ ์ค์ ์๋ต๋๋ ๋ง๋ค์ด ์์ ์ ์์ผ๋, ์์ธํ ์ฌํญ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์!
- Spring Data JPA์ ๊ธฐ๋ณธ๊ณผ ํ๋ก์ ํธ ์์ฑ :: ์๋ฆฌ์ฆ ํ์ต ํ๊ฒฝ ์ค๋น
- JPA์ ๊ธฐ๋ณธ๊ณผ Spring Data JPA
- Springboot project ์์ JPA ์ค์ ํ๊ธฐ
- JPA์ ๊ธฐ๋ณธ ์ด๋
ธํ
์ด์
๋ค :: JPA์ ์์๊ณผ ๋์์ ๋
- ์ํฐํฐ์ ํ ์ด๋ธ ๋งคํ
- ํ๋์ ์ปฌ๋ผ ๋งคํ
- ๋งคํ ํ
์ด๋ธ๊ณผ ์ฐ๊ด๊ด๊ณ ๋งคํํ๊ธฐ :: RDB์ ๊ฝ, ์ฐ๊ด ๊ด๊ณ
- ์ฐ๊ด๊ด๊ณ๋?, ์ธ๋ ํค๋?, ๋งคํ ํ ์ด๋ธ์ด๋?
- ์ผ๋์ผ, ์ผ๋๋ค, ๋ค๋์ผ ์ฐ๊ด๊ด๊ณ
- ๊ณตํต ์ธํฐํ์ด์ค ๊ธฐ๋ฅ :: ์ด๋ป๊ฒ Data JPA ๋ ๋์ํ ๊น?
- ๋จ๊ฑด ์กฐํ ๋ฐํ ํ์
- ์ปฌ๋ ์ ์กฐํ ๋ฐํ ํ์
- ์ฌ์ฉ์ ์ ์ ์ฟผ๋ฆฌ ์ด์ฉํ๋ ๋ฐฉ๋ฒ :: ๋ด๊ฐ ์ํ๋ ์ฟผ๋ฆฌ๋ฅผ JPA ์์ ๋ง๋ค์ด๋ณด์!
- ๋ฉ์๋ ์ด๋ฆ์ผ๋ก ์ฟผ๋ฆฌ ์์ฑํ๊ธฐ
@Query
๋ฅผ ์ด์ฉํ์ฌ ๋ฉ์๋์ ์ ์ ์ฟผ๋ฆฌ ์์ฑํ๊ธฐ
- ํ์ด์ง๊ณผ ์ ๋ ฌ :: ๊ฒ์ํ๊ณผ ๊ฐ์ ํ์ด์ง๊ฐ ์๋ ์๋น์ค์์ ๋น์ ๋ฐํ๋ JPA ํ์ด์ง!
- Data JPA์ ํ์ด์ง๊ณผ ์ ๋ ฌ
- Web MVC ์์ JPA ํ์ด์ง๊ณผ ์ ๋ ฌ
- Auditing :: ๋ชจ๋ ์์ฒญ๊ณผ ์๋ต์
๋๊ฐ, ์ธ์
์ ๊ทผํ๋์ง ํ๋์ ์ํฐํฐ๋ก ๊ด๋ฆฌํ์.- ์์ JPA์ Auditing
- Spring Data JPA์ Auditing
- ๋ฐฐ์๋ณด์ 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:N
- 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 ์์ ํน์ ์๋ฐ์์ ์ด์ฉํ๊ธฐ ์ํด์๋ ๋ค์ ์ด๋ ธํ ์ด์ ์ ์์์ผ ํ๋ค.
@OneToOne
: ์ผ๋์ผ ๋งคํ@OneToMany
: ์ผ๋๋ค ๋งคํ (์ฌ์ฉ์, 1) : (์ฃผ๋ฌธ ๋ชฉ๋ก, N)@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 ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ ๊ฒ
- Lombok ์
ํ ์คํธ
์ฌ๊ธฐ ๊น์ง ์ ๋๊ณ ์๋์ง๋ฅผ ํ์ธํ๊ธฐ ์ํด์ ์ง๋ ์๊ฐ๊ณผ ๋์ผํ๊ฒ ์์ ๊ฐ๋ ๋ค์ ์ฝ๋๋ก ์ฆ๋ช ํด๋ณด์.
์ฐ๋ฆฌ๊ฐ ์ฆ๋ช ํ ๊ฒ์, ํ๋์ ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ์์ดํ ์ ๊ฐ์ก์ ๋, ํด๋น ์ฃผ๋ฌธ ๋ชฉ๋ก์์ ์ฃผ๋ฌธํ ์ฌ์ฉ์ ์ด๋ฆ์ด ํด๋น ์ฌ์ฉ์์ ์ด๋ฆ๊ณผ ๋์ผํ์ง๋ฅผ ํ ์คํธํ ๊ฒ์ด๋ค.
- Entity
User
.classItem
.classOrderItem
.class
- Repository
UserRepository
.interfaceItemRepository
.interfaceOrderItemRepository
.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, ๊ณ ๋ฆฝ ์์ค์ด๋? ์ ์ฐธ๊ณ ํ๋ ๊ฒ๋ ์ข์ ๊ฒ ๊ฐ๋ค.
๋๊ธ