[공통 코드 조회 기능 개선] 공통 코드 조회 API를 개선하여, CommonGroupCode 및 Member 정보를 조인하여 함께 반환하도록 수정. 새로운 GetCommonCodeResponseDto 클래스를 추가하고, 관련 메서드를 CommonCodeService 및 CommonCodeRepository에 구현하여 데이터 조회 성능을 향상시킴.

This commit is contained in:
2025-09-03 14:57:15 +09:00
parent 230ef022c5
commit 0e6eb8a64d
6 changed files with 159 additions and 3 deletions

View File

@@ -168,8 +168,8 @@ public class CommonCodeController {
@ApiResponse(responseCode = "404", description = "공통 코드를 찾을 수 없음", content = @Content(schema = @Schema(implementation = ApiResponseDto.class)))
})
@GetMapping("/{code}")
public ResponseEntity<ApiResponseDto<CommonCodeDto>> getCode(@PathVariable String code) {
CommonCodeDto commonCode = commonCodeService.getCode(code);
public ResponseEntity<ApiResponseDto<GetCommonCodeResponseDto>> getCode(@PathVariable String code) {
GetCommonCodeResponseDto commonCode = commonCodeService.getCodeWithJoinInfo(code);
return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, commonCode));
}

View File

@@ -0,0 +1,68 @@
package com.bio.bio_backend.domain.admin.common_code.dto;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 공통 코드 조회용 Response DTO
* CommonGroupCode의 name과 Member의 name을 join을 통해 함께 조회
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@SqlResultSetMapping(
name = "GetCommonCodeResponseDtoMapping",
classes = @ConstructorResult(
targetClass = GetCommonCodeResponseDto.class,
columns = {
@ColumnResult(name = "code", type = String.class),
@ColumnResult(name = "name", type = String.class),
@ColumnResult(name = "description", type = String.class),
@ColumnResult(name = "group_code", type = String.class),
@ColumnResult(name = "parent_code", type = String.class),
@ColumnResult(name = "character_ref1", type = String.class),
@ColumnResult(name = "character_ref2", type = String.class),
@ColumnResult(name = "character_ref3", type = String.class),
@ColumnResult(name = "character_ref4", type = String.class),
@ColumnResult(name = "character_ref5", type = String.class),
@ColumnResult(name = "sort_order", type = Integer.class),
@ColumnResult(name = "use_flag", type = Boolean.class),
@ColumnResult(name = "created_at", type = LocalDateTime.class),
@ColumnResult(name = "updated_at", type = LocalDateTime.class),
@ColumnResult(name = "group_code_name", type = String.class),
@ColumnResult(name = "created_by_name", type = String.class),
@ColumnResult(name = "updated_by_name", type = String.class)
}
)
)
public class GetCommonCodeResponseDto {
// CommonCode 기본 정보
private String code;
private String name;
private String description;
private String groupCode;
private String parentCode;
private String characterRef1;
private String characterRef2;
private String characterRef3;
private String characterRef4;
private String characterRef5;
private Integer sortOrder;
private Boolean useFlag;
// BaseEntity 정보
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
// Join을 통해 가져올 정보
private String groupCodeName; // CommonGroupCode의 name
private String createdByName; // 생성자 Member의 name
private String updatedByName; // 수정자 Member의 name
}

View File

@@ -1,7 +1,9 @@
package com.bio.bio_backend.domain.admin.common_code.repository;
import com.bio.bio_backend.domain.admin.common_code.dto.GetCommonCodeResponseDto;
import com.bio.bio_backend.domain.admin.common_code.entity.CommonCode;
import java.util.List;
import java.util.Optional;
/**
* QueryDSL을 활용한 커스텀 쿼리 메서드들을 정의하는 인터페이스
@@ -24,4 +26,22 @@ public interface CommonCodeRepositoryCustom {
* @return List<CommonCode> 활성화된 공통 코드 목록
*/
List<CommonCode> findByParentCode(String parentCode);
/**
* 특정 공통 코드를 조회하며 CommonGroupCode와 Member 정보를 join하여 함께 조회합니다.
* QueryDSL을 사용하여 성능 최적화된 쿼리를 실행합니다.
*
* @param code 조회할 공통 코드
* @return Optional<GetCommonCodeResponseDto> 조회된 공통 코드 정보 (없으면 empty)
*/
Optional<GetCommonCodeResponseDto> findCodeWithJoinInfo(String code);
/**
* 특정 공통 코드를 조회하며 CommonGroupCode와 Member 정보를 join하여 함께 조회합니다.
* Native Query를 사용한 버전 (사용하지 않음, 참고용)
*
* @param code 조회할 공통 코드
* @return Optional<GetCommonCodeResponseDto> 조회된 공통 코드 정보 (없으면 empty)
*/
Optional<GetCommonCodeResponseDto> findCodeWithJoinInfoNative(String code);
}

View File

@@ -1,12 +1,18 @@
package com.bio.bio_backend.domain.admin.common_code.repository;
import com.bio.bio_backend.domain.admin.common_code.dto.GetCommonCodeResponseDto;
import com.bio.bio_backend.domain.admin.common_code.entity.CommonCode;
import com.bio.bio_backend.domain.admin.common_code.entity.QCommonCode;
import com.bio.bio_backend.domain.admin.common_code.entity.QCommonGroupCode;
import com.bio.bio_backend.domain.base.member.entity.QMember;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* QueryDSL을 활용하여 CommonCodeRepositoryCustom 인터페이스를 구현하는 클래스
@@ -17,12 +23,16 @@ import java.util.List;
public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
private final JPAQueryFactory queryFactory;
private final EntityManager entityManager;
/**
* QCommonCode 인스턴스 생성하여 쿼리에서 사용합니다.
* Q클래스 인스턴스들을 생성하여 쿼리에서 사용합니다.
* QueryDSL의 Q클래스를 통해 타입 안전한 쿼리 작성이 가능합니다.
*/
private final QCommonCode commonCode = QCommonCode.commonCode;
private final QCommonGroupCode commonGroupCode = QCommonGroupCode.commonGroupCode;
private final QMember createdByMember = new QMember("createdByMember");
private final QMember updatedByMember = new QMember("updatedByMember");
@Override
public List<CommonCode> findByGroupCode(String groupCode) {
@@ -43,4 +53,53 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
.orderBy(commonCode.sortOrder.asc())
.fetch();
}
@Override
public Optional<GetCommonCodeResponseDto> findCodeWithJoinInfo(String code) {
return Optional.ofNullable(
queryFactory
.select(Projections.constructor(GetCommonCodeResponseDto.class,
commonCode.code, commonCode.name, commonCode.description,
commonCode.groupCode, commonCode.parentCode,
commonCode.characterRef1, commonCode.characterRef2, commonCode.characterRef3,
commonCode.characterRef4, commonCode.characterRef5,
commonCode.sortOrder, commonCode.useFlag,
commonCode.createdAt, commonCode.updatedAt,
commonGroupCode.name, createdByMember.name, updatedByMember.name
))
.from(commonCode)
.leftJoin(commonGroupCode).on(commonCode.groupCode.eq(commonGroupCode.code))
.leftJoin(createdByMember).on(commonCode.createdOid.eq(createdByMember.oid))
.leftJoin(updatedByMember).on(commonCode.updatedOid.eq(updatedByMember.oid))
.where(commonCode.code.eq(code))
.fetchOne()
);
}
@Override
public Optional<GetCommonCodeResponseDto> findCodeWithJoinInfoNative(String code) {
String nativeQuery = """
SELECT cc.code, cc.name, cc.description, cc.group_code, cc.parent_code,
cc.character_ref1, cc.character_ref2, cc.character_ref3, cc.character_ref4, cc.character_ref5,
cc.sort_order, cc.use_flag, cc.created_at, cc.updated_at,
cgc.name as group_code_name, cm1.name as created_by_name, cm2.name as updated_by_name
FROM st_common_code cc
LEFT JOIN st_common_group_code cgc ON cc.group_code = cgc.code
LEFT JOIN st_member cm1 ON cc.created_oid = cm1.oid
LEFT JOIN st_member cm2 ON cc.updated_oid = cm2.oid
WHERE cc.code = :code
""";
try {
@SuppressWarnings("unchecked")
List<GetCommonCodeResponseDto> results = entityManager
.createNativeQuery(nativeQuery, "GetCommonCodeResponseDtoMapping")
.setParameter("code", code)
.getResultList();
return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
} catch (Exception e) {
return Optional.empty();
}
}
}

View File

@@ -2,6 +2,7 @@ package com.bio.bio_backend.domain.admin.common_code.service;
import com.bio.bio_backend.domain.admin.common_code.dto.CommonCodeDto;
import com.bio.bio_backend.domain.admin.common_code.dto.CommonGroupCodeDto;
import com.bio.bio_backend.domain.admin.common_code.dto.GetCommonCodeResponseDto;
import java.util.List;
@@ -20,6 +21,7 @@ public interface CommonCodeService {
void updateCode(String code, CommonCodeDto codeDto);
void deleteCode(String code);
CommonCodeDto getCode(String code);
GetCommonCodeResponseDto getCodeWithJoinInfo(String code);
List<CommonCodeDto> getActiveCodesByGroupCode(String groupCode);
List<CommonCodeDto> getActiveCodesByParentCode(String parentCode);
List<CommonCodeDto> getAllCodes();

View File

@@ -2,6 +2,7 @@ package com.bio.bio_backend.domain.admin.common_code.service;
import com.bio.bio_backend.domain.admin.common_code.dto.CommonCodeDto;
import com.bio.bio_backend.domain.admin.common_code.dto.CommonGroupCodeDto;
import com.bio.bio_backend.domain.admin.common_code.dto.GetCommonCodeResponseDto;
import com.bio.bio_backend.domain.admin.common_code.entity.CommonCode;
import com.bio.bio_backend.domain.admin.common_code.entity.CommonGroupCode;
import com.bio.bio_backend.domain.admin.common_code.mapper.CommonCodeMapper;
@@ -133,6 +134,12 @@ public class CommonCodeServiceImpl implements CommonCodeService {
return commonCodeMapper.toCommonCodeDto(commonCode);
}
@Override
public GetCommonCodeResponseDto getCodeWithJoinInfo(String code) {
return commonCodeRepository.findCodeWithJoinInfo(code)
.orElseThrow(() -> new ApiException(ApiResponseCode.COMMON_CODE_ERROR_003));
}
@Override
public List<CommonCodeDto> getActiveCodesByGroupCode(String groupCode) {
List<CommonCode> commonCodes = commonCodeRepository.findByGroupCode(groupCode);