Back-end/TIL

[SpringBoot] JPAλ₯Ό 톡해 μ—”ν‹°ν‹° λ°˜ν™˜μ‹œ DtoVo μ‚¬μš©ν•˜κΈ°

sw_develop 2022. 3. 16. 09:28

πŸ“Œ 상황

Spring Data JPAλ₯Ό 톡해 μ—”ν‹°ν‹° μ‘°νšŒμ‹œ κΈ°μ‘΄μ—λŠ” μ•„λž˜μ™€ 같이 μ½”λ“œλ₯Ό μž‘μ„±ν•˜μ˜€λ‹€.

//κΈ°μ‘΄ μ½”λ“œ
Page<PharmacyMenu> findByMenuKorNameContains(String menuKorName, Pageable pageable);
Page<PharmacyMenu> findByMenuEngNameIgnoreCaseContains(String menuEngName, Pageable pageable);

 

μœ„μ˜ μ½”λ“œκ°€ ν‹€λ¦° 것은 μ•„λ‹ˆμ§€λ§Œ, λͺ‡κ°€μ§€ 문제점이 μ‘΄μž¬ν•œλ‹€.

 

1. 기쑴의 방식은 μ—”ν‹°ν‹° μžμ²΄κ°€ λ°˜ν™˜λ˜κΈ° λ•Œλ¬Έμ— λ§Œμ•½ μ‘°νšŒμ‹œ νŠΉμ • ν•„λ“œ κ°’λ§Œ ν•„μš”ν•˜λ‹€λ©΄, λΆˆν•„μš”ν•œ ν•„λ“œ 값이 λͺ¨λ‘ λ°˜ν™˜λ˜λŠ” 상황이닀.

2. λΆˆν•„μš”ν•œ ν•„λ“œκ°€ λ§Žκ±°λ‚˜ ν•΄λ‹Ή ν•„λ“œμ˜ νƒ€μž…μ΄ text와 같이 μ‚¬μ΄μ¦ˆκ°€ 크닀면, μ„±λŠ₯ μ΄μŠˆκ°€ λ°œμƒν•  수 μžˆλ‹€. 즉, 기쑴의 방식은 SELECT * FROM κ³Ό 같은 κ²½μš°μ΄λ‹€.

 

πŸ“Œ κ°œμ„ 

ν•„μš”ν•œ ν•„λ“œλ§Œ μ„ μ–Έν•΄λ‘” DtoVo 클래슀λ₯Ό λ³„λ„λ‘œ κ΅¬μ„±ν•˜μ—¬ μ—”ν‹°ν‹° 자체 μ‘°νšŒκ°€ μ•„λ‹Œ νŠΉμ • ν•„λ“œλ“€ 쑰회둜 κ°œμ„ μ΄ κ°€λŠ₯ν•˜λ‹€.

//DtoVo μ˜ˆμ‹œ
@Getter
public class PharmMenuListResDtoVo {

    private Long id;
    private String menuKorName;
    private String menuEngName;
    private String menuUrlPath;
    private int menuOrder;
    
    @Builder
    public PharmMenuListResDtoVo(Long id, String menuKorName, String menuEngName, String menuUrlPath, int menuOrder) {
    	this.id = id;
        this.menuKorName = menuKorName;
        this.menuEngName = menuEngName;
        this.menuUrlPath = menuUrlPath;
        this.menuOrder = menuOrder;
    }
}

 

DtoVo 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ λ³€κ²½ν•œ 쑰회 μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

//쑰회 μ½”λ“œ λ³€κ²½ μ˜ˆμ‹œ
@Query("select pm.id as id, " +
            "pm.menuKorName as menuKorName, " +
            "pm.menuEngName as menuEngName, " +
            "pm.menuUrlPath as menuUrlPath, " +
            "pm.menuOrder as menuOrder " +
            "from PharmacyMenu pm " +
            "where (pm.menuKorName like %:menuName% or pm.menuEngName like %:menuName%)")
Page<PharmMenuListResDtoVo> findByMenuName(@Param("menuName") String menuName, Pageable pageable);
  • JPQL둜 쿼리λ₯Ό μž‘μ„±ν•΄ μ—”ν‹°ν‹°μ—μ„œ ν•„μš”ν•œ ν•„λ“œλ§Œ κ°€μ Έμ˜€λ„λ‘ ν•œλ‹€.
  • μœ„μ—μ„œ @Query()λ‚΄μ˜ as λ’€μ˜ {λ³€μˆ˜λͺ…}κ³Ό DtoVo 클래슀 λ‚΄μ˜ ν•„λ“œλͺ…을 맞좰주면 Spring Data JPAκ°€ μžλ™μœΌλ‘œ λ§€ν•‘ν•΄μ€€λ‹€. 이후 Service 클래슀 λ‚΄μ—μ„œ DTO둜 λ³€κ²½ν•  λ•Œ μœ μš©ν•˜λ‹€.

 

πŸ“Œ Entity와 DTO κ°„ λ³€ν™˜ν•˜λŠ” 방식

방식1 - Mapper μ‚¬μš©

단점: μ—λŸ¬ λ°œμƒμ‹œ μ°ΎκΈ° μ–΄λ ΅λ‹€.

 

방식2 - 각각의 ν•„λ“œλ₯Ό 일일이 λ§€ν•‘

 

방식3 - Spring의 Pageλ₯Ό μ‚¬μš©ν•˜λŠ” 경우 Page μΈν„°νŽ˜μ΄μŠ€μ˜ map() μ‚¬μš©

//μ½”λ“œ μ˜ˆμ‹œ
public Page<PharmMenuDto.PharmMenuListResDto> getPharmMenuList(PharmMenuDto.PharmMenuListReqDto pharmMenuListReqDto) {

        Pageable pageable = PageRequest.of(pharmMenuListReqDto.getPage(), pharmMenuListReqDto.getSize()); //전달할 Pageable 객체 생성

        Page<PharmMenuListResDtoVo> pharmMenuListResDtoVos = pharmacyMenuRepository.findByMenuName(pharmMenuListReqDto.getMenuName(), pageable);

        return pharmMenuListResDtoVos.map(pml -> new PharmMenuDto.PharmMenuListResDto(
                pml.getId(), pml.getMenuKorName(), pml.getMenuEngName(), pml.getMenuUrlPath(), pml.getMenuOrder()
        )); //Page μΈν„°νŽ˜μ΄μŠ€μ˜ map() μ‚¬μš©ν•˜μ—¬ DTO둜 λ§€ν•‘
   }