@Transactional
@SpringBootTest
@ActiveProfiles("test")
class ProductListResponseDtoTest {
@Autowired ProductRepository productRepository;
@Test
@DisplayName("์ฃผ๋ฌธ ์์ธ๊ฐ ์ฃผ์ด์ก์ ๋ ProductListResponseDto ๋ณํ")
public void ofWithOrderDetail() {
Product product = Product.builder()
.price(1000L)
.name("๋นต๋นต์ด")
.productNo("123")
.build();
productRepository.save(product);
OrderDetail orderDetail = OrderDetail.builder()
.product(product)
.price(product.getPrice())
.quantity(2L)
.build();
// when
ProductListResponseDto result = ProductListResponseDto.of(orderDetail);
// then
assertThat(result).extracting("productId", "productNo", "name", "price", "quantity")
.contains(1L, "123", "๋นต๋นต์ด", 1000L, 2L);
}
@Test
@DisplayName("์ํ๊ณผ ์๋์ด ์ฃผ์ด์ก์ ๋ ProductListResponseDto ๋ณํ")
public void ofWithProductAndQuantity() {
Long quantity = 2L;
Product product = Product.builder()
.price(1000L)
.name("๋นต๋นต์ด")
.productNo("123")
.build();
productRepository.save(product);
// when
ProductListResponseDto result = ProductListResponseDto.of(product, quantity);
// then
assertThat(result).extracting("productId", "productNo", "name", "price", "quantity")
.contains(1L, "123", "๋นต๋นต์ด", 1000L, 2L);
}
@Transactional๋ฅผ ํตํด ๊ฐ ํ ์คํธ๊ฐ ๋กค๋ฐฑ๋์ด productId๊ฐ ๋ชจ๋ 1L ๋ ๊ฒ์ผ๋ก ์์ํ๋ค.
๊ธฐ๋์ ๋ฌ๋ฆฌ ์คํจ๋ฅผ ํ์๋ค. ์ฒซ๋ฒ์งธ ํ ์คํธ(ofWithOrderDetail)์ productId์ ๊ฐ์ด 2L ๋์๋ค. ๋ญ์ผ.. ์..?
์ฒ์์๋ ๋กค๋ฐฑ์ด ์๋๋? ์๊ฐํ์ง๋ง
Hibernate:
insert
into
product
(category_id, created_at, deleted_at, discount_rate, is_own, is_subs, name, price, product_no, stock, thumb_img, updated_at, product_id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, default)
2024-01-29T22:28:07.219+09:00 INFO 3636 --- [ main] p6spy : #1706534887219 | took 4ms | statement | connection 3| url jdbc:h2:mem:~/Marketbridge
insert into product (category_id,created_at,deleted_at,discount_rate,is_own,is_subs,name,price,product_no,stock,thumb_img,updated_at,product_id) values (?,?,?,?,?,?,?,?,?,?,?,?,default)
insert into product (category_id,created_at,deleted_at,discount_rate,is_own,is_subs,name,price,product_no,stock,thumb_img,updated_at,product_id) values (NULL,NULL,NULL,NULL,NULL,NULL,'๋นต๋นต์ด',1000,'123',NULL,NULL,NULL,default);
2024-01-29T22:28:07.299+09:00 INFO 3636 --- [ main] p6spy : #1706534887299 | took 0ms | rollback | connection 3| url jdbc:h2:mem:~/Marketbridge
;
Hibernate:
insert
into
product
(category_id, created_at, deleted_at, discount_rate, is_own, is_subs, name, price, product_no, stock, thumb_img, updated_at, product_id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, default)
2024-01-29T22:28:07.309+09:00 INFO 3636 --- [ main] p6spy : #1706534887309 | took 0ms | statement | connection 4| url jdbc:h2:mem:~/Marketbridge
insert into product (category_id,created_at,deleted_at,discount_rate,is_own,is_subs,name,price,product_no,stock,thumb_img,updated_at,product_id) values (?,?,?,?,?,?,?,?,?,?,?,?,default)
insert into product (category_id,created_at,deleted_at,discount_rate,is_own,is_subs,name,price,product_no,stock,thumb_img,updated_at,product_id) values (NULL,NULL,NULL,NULL,NULL,NULL,'๋นต๋นต์ด',1000,'123',NULL,NULL,NULL,default);
2024-01-29T22:28:07.317+09:00 INFO 3636 --- [ main] p6spy : #1706534887317 | took 0ms | rollback | connection 4| url jdbc:h2:mem:~/Marketbridge
;
insert๋ฌธ์ ๋ณด๋ฉด rollback์ด ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ฆฌ ์ ๋ฆฌ ์ฝ์งํ๋ ์ค ์ํฐํฐ์ ID๊ฐ Identity์ ๋ต์ผ๋ก ๋ง๋ค์ด์ง๊ณ ์์๋๋ฐ ์ด๊ฒ์ด ๋ฌธ์ ๊ฐ ๋๊ณ ์์๋ค...
์ ์ IDENTITY ๋ํด ์์๋ณด์.
IDENTITY ์ ๋ต์ ๋ถ๋ช
ํ ๋จ์ ์ ๊ฐ์ง๊ณ ์๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ์ ์ฅํ๊ณ ๋์์ผ ๊ธฐ๋ณธ ํค ๊ฐ์ ๊ตฌํ ์ ์๋ค.
์ด๊ฒ์ด ๋ฌด์จ ๋ง์ด๋? ์์์ฑ ์ปจํ
์คํธ์ 1์ฐจ ์บ์(์์ํ)๋ฅผ ํ ๋ ์ํฐํฐ๋ Id๋ฅผ ๋ฌด~์กฐ๊ฑด ๊ฐ์ง๊ณ ์์ด์ผ ํ๋๋ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ์ ๊ณตํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋จ์ํ ํค๋ฅผ ์ป๋ ๊ณผ์ ์ธ๋ฐ๋ ๋ถ๊ตฌํ๊ณ ๋คํธ์ํฌ๋ฅผ ํ ๋ฒ ํ์ผํ๋ ๋ถ์์ฌ๊ฐ ์ผ์ด๋๋ค.
์ ๋ฆฌํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ Id๋ฅผ ๋ฐ์์จ ํ ์์์ฑ ์ปจํ ์คํธ์ ์บ์๊ฐ ๋๋ค.
๋ง์ฝ ์ด๊ฒ ์ซ๋ค๋ฉด? SEQUENCE ์ ๋ต์ ํ ๋ฒ ์์๋ณด๋ ๊ฒ์ ์ถ์ฒํ๋ค!
์ต์ ํ ๋ถ๋ถ์์ ์ด๋์ ์ป์ ์ ์์ ๊ฒ์ด๋ค.
IDENTITY ์ ๋ต์ ๋ํด ๋์ถฉ ์์๋ณด์๋๋ฐ ๋๋์ฒด ์ด๊ฒ ํ ์คํธ์์ ์ด๋ค ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๊ฑธ๊น?
IDENTITY ์ ๋ต์ ์ฌ์ฉํ ๋ ์ฃผ์ํ ์ ์ด ์กด์ฌํ๋ค.
AUTO INCREMENT ๋ Transaction ์ ์ฌ์ฉํด๋ rollback ๋์ง ์๋๋ค.
์ด๊ฒ ๋ฌด์จ๋ง์ด๋๋ฉด, Insert ์ฟผ๋ฆฌ๋ฅผ ์คํจํด๋ Table ์ AUTO INCREMENT ์ปฌ๋ผ์ ๊ฐ์ 1์ด ์ฆ๊ฐ๋๋ค.
์์ ํ ์คํธ๋ฅผ ๋ค์ ์๋ก ๋ค์ด๋ณด๋ฉด IDENTITY ์ ๋ต์ rollback์ด ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ฒ์งธ๋ก ์งํ๋ ํ ์คํธ์ productId๊ฐ 2๊ฐ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ ํด๊ฒฐํด์ผ ํ ๊น?
AUTO INCREMENT ๊ฐ์ ์ ๋ขฐํด์๋ ์๋๋ค. ๋ง์ฝ AUTO INCREMENT ๊ฐ์ ์ค์ํ๊ฒ ์ฌ์ฉํ๋ค๋ฉด, innodb_autoinc_lock_mode์ ์ ์์์ผํ๋ค.
innodb_autoinc_lock_mode์ ๋ํด์๋ ๋ฐ๋ก ์์๋ณด์ง ์๊ฒ ๋ค. ํ์ํ๋ค๋ฉด ๊ฒ์ํด์ ๋ณด๋ ๊ฒ์ ์ถ์ฒํ๊ฒ ๋น
์ง๊ธ ํ๋ก์ ํธ๋ my-sql์ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ IDENTITY์ ๋ต์ ๋ฐ๊ฟ ์ ์์๊ฒ์ผ๋ก ์๊ฐ๋๋ค.
๊ทธ๋ ๋ค๊ณ innodb_autoinc_lock_mode๋ฅผ ๊ณต๋ถํด์ ์ ์ฉํ๊ธฐ์ db๋ฌด๋ํ์ผ๋ก์๋ ์คํ๋ฆฐํธ๋ฅผ ํด์ผํ๋ ์ง๊ธ ์๊ธฐ์ ์ด๋ ค์๋ณด์ธ๋ค. (์๋ฌด๊ฒ๋ ๋ชจ๋ฅด๊ธฐ์ ์๊ฐ ์์ธก์ด ์๋๊ธฐ ๋๋ฌธ,,,ใ
ใ
)
์ง๊ธ ๋จ์ํ ํ ์คํธ๋ฅผ ํ๋๋ฐ Id๋ฅผ ์ํด์ ์คํ๋ง์ ๋์ฐ๋ ๊ฒ๊ณผ db๋ฅผ ๊ณต๋ถํ๋ ๊ฒ ๋๊ฐ ๋ค ๋ถ๋ด์ค๋ฝ๊ธฐ ๋๋ฌธ์ Reflection์ ํตํด ์คํ๋ง ์์ด ๋จ์ํ ์คํธ๋ฅผ ์งํ ํ ์์ ์ด๋ค. Id๋ง ๋ฃ์ด์ฃผ๋ฉด ๋๋๊น..! ์ด ๋ฐฉ๋ฒ์ด ์ง๊ธ ์ํฉ์์ ์ข์ ํ๋จ์ด๋ผ๊ณ ์๊ฐ๋๋ค.
class ProductListResponseDtoTest {
@Test
@DisplayName("์ฃผ๋ฌธ ์์ธ๊ฐ ์ฃผ์ด์ก์ ๋ ProductListResponseDto ๋ณํ")
public void ofWithOrderDetail() {
Product product = Product.builder()
.price(1000L)
.name("๋นต๋นต์ด")
.productNo("123")
.build();
ReflectionTestUtils.setField(product, "id", 1L, Long.class);
OrderDetail orderDetail = OrderDetail.builder()
.product(product)
.price(product.getPrice())
.quantity(2L)
.build();
// when
ProductListResponseDto result = ProductListResponseDto.of(orderDetail);
// then
assertThat(result).extracting("productId", "productNo", "name", "price", "quantity")
.contains(1L, "123", "๋นต๋นต์ด", 1000L, 2L);
}
@Test
@DisplayName("์ํ๊ณผ ์๋์ด ์ฃผ์ด์ก์ ๋ ProductListResponseDto ๋ณํ")
public void ofWithProductAndQuantity() {
Long quantity = 2L;
Product product = Product.builder()
.price(1000L)
.name("๋นต๋นต์ด")
.productNo("123")
.build();
ReflectionTestUtils.setField(product, "id", 1L, Long.class);
// when
ProductListResponseDto result = ProductListResponseDto.of(product, quantity);
// then
assertThat(result).extracting("productId", "productNo", "name", "price", "quantity")
.contains(1L, "123", "๋นต๋นต์ด", 1000L, 2L);
}
}
ReflectionTestUtils๋ฅผ ํตํด ๊ฐ์ ์
ํ
ํด์ฃผ์๋ค.
์คํ๋ง ์์ด ๋จ์ํ
์คํธ๋ก ์งํํ๊ธฐ ๋๋ฌธ์ ํจ์ฌ ๋น ๋ฅธ ์๋๋ฅผ ๋ณด์ธ๋ค!!