๐Ÿ’ป Knowledge/ํ…Œ์ŠคํŠธ์ฝ”๋“œ

Persistence Layer ํ…Œ์ŠคํŠธ

ming412 2024. 12. 19. 10:33

Repository ํ…Œ์ŠคํŠธ๋ฅผ ์™œ ํ•ด์•ผํ• ๊นŒ?

1. JPA ๋ฉ”์„œ๋“œ๊ฐ€ ์ž‘์„ฑ์ž์˜ ์˜๋„๋Œ€๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด

๊ฐœ๋ฐœ์ž๋Š” ์ฝ”๋“œ์— ๊ธฐ๋ฐ˜ํ•œ ๋กœ์ง์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•œ๋‹ค๊ณ  ๋ฏฟ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ์ƒ์„ฑ๋œ ์ฟผ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค!

 

2. ๋ฏธ๋ž˜์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์— ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด

ํ˜„์žฌ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ํ–ฅํ›„ QueryDSL, MyBatis์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ๊ธฐ์ˆ ๋กœ ๋ณ€๊ฒฝ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. Repository ํ…Œ์ŠคํŠธ๋ฅผ ์ž˜ ๊ตฌ์„ฑํ•ด ๋‘๋ฉด, ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์—๋„ ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Repository ์ฝ”๋“œ

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    /**
     * select *
     * from product
     * where selling_status in ('SELLING', 'HOLD');
     */
    List<Product> findAllBySellingStatusIn(List<ProductSellingStatus> sellingStatuses);

}

 

RepositoryTest ์ฝ”๋“œ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ, ์•„๋ž˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์กฐํ•ฉํ•˜๋ฉด ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

โœ… `.hasSize` : ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค.

โœ… `.extracting` : ๋ฆฌ์ŠคํŠธ ๋‚ด ๊ฐ์ฒด์—์„œ ํŠน์ • ํ•„๋“œ๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๊ฒ€์ฆํ•œ๋‹ค.

โœ… `.containsExactlyInAnyOrder` : ๋ฆฌ์ŠคํŠธ์— ํŠน์ • ๊ฐ’๋“ค์ด ๋ชจ๋‘ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•œ๋‹ค. (์ˆœ์„œ์™€ ์ƒ๊ด€ ์—†์Œ)

assertThat(products).hasSize(2)
    .extracting("productNumber", "name", "sellingStatus")
    .containsExactlyInAnyOrder(
            tuple("001", "์•„๋ฉ”๋ฆฌ์นด๋…ธ", SELLING),
            tuple("002", "์นดํŽ˜๋ผ๋–ผ", HOLD)
);

 

์ „์ฒด ์ฝ”๋“œ

@ActiveProfiles("test")
//@SpringBootTest
@DataJpaTest
class ProductRepositoryTest {

    @Autowired
    private ProductRepository productRepository;

    @DisplayName("์›ํ•˜๋Š” ํŒ๋งค์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ์ƒํ’ˆ๋“ค์„ ์กฐํšŒํ•œ๋‹ค.")
    @Test
    void findAllBySellingStatusIn() {
        // given
        Product product1 = Product.builder()
                .productNumber("001")
                .type(HANDMADE)
                .sellingStatus(SELLING)
                .name("์•„๋ฉ”๋ฆฌ์นด๋…ธ")
                .price(4000)
                .build();
        Product product2 = Product.builder()
                .productNumber("002")
                .type(HANDMADE)
                .sellingStatus(HOLD)
                .name("์นดํŽ˜๋ผ๋–ผ")
                .price(4500)
                .build();
        Product product3 = Product.builder()
                .productNumber("003")
                .type(HANDMADE)
                .sellingStatus(STOP_SELLING)
                .name("ํŒฅ๋น™์ˆ˜")
                .price(7000)
                .build();
        productRepository.saveAll(List.of(product1, product2, product3));

        // when
        List<Product> products = productRepository.findAllBySellingStatusIn(List.of(SELLING, HOLD));

        // then
        assertThat(products).hasSize(2)
                .extracting("productNumber", "name", "sellingStatus")
                .containsExactlyInAnyOrder(
                        tuple("001", "์•„๋ฉ”๋ฆฌ์นด๋…ธ", SELLING),
                        tuple("002", "์นดํŽ˜๋ผ๋–ผ", HOLD)
                );
    }

}