test api 추가, 개발서버 토큰 만료시간 조정

This commit is contained in:
2025-12-11 17:06:36 +09:00
parent d18e4db060
commit ce8534cf0f
4 changed files with 227 additions and 231 deletions

View File

@@ -6,7 +6,6 @@ import org.springframework.http.HttpStatus;
@Getter @Getter
public enum AuthErrorCode implements ErrorCode { public enum AuthErrorCode implements ErrorCode {
LOGIN_ID_NOT_FOUND("LOGIN_ID_NOT_FOUND", HttpStatus.UNAUTHORIZED), LOGIN_ID_NOT_FOUND("LOGIN_ID_NOT_FOUND", HttpStatus.UNAUTHORIZED),
LOGIN_PASSWORD_MISMATCH("LOGIN_PASSWORD_MISMATCH", HttpStatus.UNAUTHORIZED), LOGIN_PASSWORD_MISMATCH("LOGIN_PASSWORD_MISMATCH", HttpStatus.UNAUTHORIZED),

View File

@@ -54,59 +54,59 @@ public class AuthController {
@Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.") @Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그인 성공", description = "로그인 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "401", responseCode = "401",
description = "로그인 실패 (아이디/비밀번호 오류, 계정잠금 등)", description = "로그인 실패 (아이디/비밀번호 오류, 계정잠금 등)",
content = content =
@Content( @Content(
schema = @Schema(implementation = ErrorResponse.class), schema = @Schema(implementation = ErrorResponse.class),
examples = { examples = {
@ExampleObject( @ExampleObject(
name = "아이디 입력 오류", name = "아이디 입력 오류",
description = "존재하지 않는 아이디", description = "존재하지 않는 아이디",
value = value =
""" """
{ {
"code": "LOGIN_ID_NOT_FOUND", "code": "LOGIN_ID_NOT_FOUND",
"message": "아이디를 잘못 입력하셨습니다." "message": "아이디를 잘못 입력하셨습니다."
} }
"""), """),
@ExampleObject( @ExampleObject(
name = "비밀번호 입력 오류 (4회 이하)", name = "비밀번호 입력 오류 (4회 이하)",
description = "아이디는 정상, 비밀번호를 여러 번 틀린 경우", description = "아이디는 정상, 비밀번호를 여러 번 틀린 경우",
value = value =
""" """
{ {
"code": "LOGIN_PASSWORD_MISMATCH", "code": "LOGIN_PASSWORD_MISMATCH",
"message": "비밀번호를 잘못 입력하셨습니다." "message": "비밀번호를 잘못 입력하셨습니다."
} }
"""), """),
@ExampleObject( @ExampleObject(
name = "비밀번호 오류 횟수 초과", name = "비밀번호 오류 횟수 초과",
description = "비밀번호 5회 이상 오류로 계정 잠김", description = "비밀번호 5회 이상 오류로 계정 잠김",
value = value =
""" """
{ {
"code": "LOGIN_PASSWORD_EXCEEDED", "code": "LOGIN_PASSWORD_EXCEEDED",
"message": "비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다. 로그인 오류에 대해 관리자에게 문의하시기 바랍니다." "message": "비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다. 로그인 오류에 대해 관리자에게 문의하시기 바랍니다."
} }
""") """)
})) }))
}) })
public ApiResponseDto<TokenResponse> signin( public ApiResponseDto<TokenResponse> signin(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "로그인 요청 정보", description = "로그인 요청 정보",
required = true) required = true)
@RequestBody @RequestBody
SignInRequest request, SignInRequest request,
HttpServletResponse response) { HttpServletResponse response) {
Authentication authentication = Authentication authentication =
authenticationManager.authenticate( authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())); new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
String status = authService.getUserStatus(request); String status = authService.getUserStatus(request);
@@ -124,17 +124,17 @@ public class AuthController {
// Redis에 RefreshToken 저장 (TTL = 7일) // Redis에 RefreshToken 저장 (TTL = 7일)
refreshTokenService.save( refreshTokenService.save(
username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// HttpOnly + Secure 쿠키에 RefreshToken 저장 // HttpOnly + Secure 쿠키에 RefreshToken 저장
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, refreshToken) ResponseCookie.from(refreshCookieName, refreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
@@ -153,16 +153,16 @@ public class AuthController {
@Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.") @Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "재발급 성공", description = "재발급 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "403", responseCode = "403",
description = "만료되었거나 유효하지 않은 리프레시 토큰", description = "만료되었거나 유효하지 않은 리프레시 토큰",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response)
throws AccessDeniedException { throws AccessDeniedException {
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) { if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다."); throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
} }
@@ -179,17 +179,17 @@ public class AuthController {
// Redis 갱신 // Redis 갱신
refreshTokenService.save( refreshTokenService.save(
username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// 쿠키 갱신 // 쿠키 갱신
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, newRefreshToken) ResponseCookie.from(refreshCookieName, newRefreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
MembersDto.Member member = new MembersDto.Member(); MembersDto.Member member = new MembersDto.Member();
@@ -200,12 +200,12 @@ public class AuthController {
@Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.") @Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그아웃 성공", description = "로그아웃 성공",
content = @Content(schema = @Schema(implementation = Void.class))) content = @Content(schema = @Schema(implementation = Void.class)))
}) })
public ApiResponseDto<ResponseEntity<Object>> logout( public ApiResponseDto<ResponseEntity<Object>> logout(
Authentication authentication, HttpServletResponse response) { Authentication authentication, HttpServletResponse response) {
if (authentication != null) { if (authentication != null) {
String username = authentication.getName(); String username = authentication.getName();
// Redis에서 RefreshToken 삭제 // Redis에서 RefreshToken 삭제
@@ -214,13 +214,13 @@ public class AuthController {
// 쿠키 삭제 (Max-Age=0) // 쿠키 삭제 (Max-Age=0)
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, "") ResponseCookie.from(refreshCookieName, "")
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(0) .maxAge(0)
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ApiResponseDto.createOK(ResponseEntity.noContent().build()); return ApiResponseDto.createOK(ResponseEntity.noContent().build());

View File

@@ -40,11 +40,11 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
private final QModelVerEntity tmv = QModelVerEntity.modelVerEntity; private final QModelVerEntity tmv = QModelVerEntity.modelVerEntity;
private final QMapSheetAnalEntity mapSheetAnalEntity = QMapSheetAnalEntity.mapSheetAnalEntity; private final QMapSheetAnalEntity mapSheetAnalEntity = QMapSheetAnalEntity.mapSheetAnalEntity;
private final QMapSheetAnalDataEntity mapSheetAnalDataEntity = private final QMapSheetAnalDataEntity mapSheetAnalDataEntity =
QMapSheetAnalDataEntity.mapSheetAnalDataEntity; QMapSheetAnalDataEntity.mapSheetAnalDataEntity;
private final QMapSheetAnalDataGeomEntity mapSheetAnalDataGeomEntity = private final QMapSheetAnalDataGeomEntity mapSheetAnalDataGeomEntity =
QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity;
private final QMapSheetAnalSttcEntity mapSheetAnalSttcEntity = private final QMapSheetAnalSttcEntity mapSheetAnalSttcEntity =
QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity; QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity;
/** /**
* 분석결과 목록 조회 * 분석결과 목록 조회
@@ -54,7 +54,7 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
*/ */
@Override @Override
public Page<InferenceResultDto.AnalResList> getInferenceResultList( public Page<InferenceResultDto.AnalResList> getInferenceResultList(
InferenceResultDto.SearchReq searchReq) { InferenceResultDto.SearchReq searchReq) {
Pageable pageable = searchReq.toPageable(); Pageable pageable = searchReq.toPageable();
// "0000" 전체조회 // "0000" 전체조회
BooleanBuilder builder = new BooleanBuilder(); BooleanBuilder builder = new BooleanBuilder();
@@ -68,35 +68,35 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
} }
List<InferenceResultDto.AnalResList> content = List<InferenceResultDto.AnalResList> content =
queryFactory queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
InferenceResultDto.AnalResList.class, InferenceResultDto.AnalResList.class,
mapSheetAnalEntity.id, mapSheetAnalEntity.id,
mapSheetAnalEntity.analTitle, mapSheetAnalEntity.analTitle,
mapSheetAnalEntity.analMapSheet, mapSheetAnalEntity.analMapSheet,
mapSheetAnalEntity.detectingCnt, mapSheetAnalEntity.detectingCnt,
mapSheetAnalEntity.analStrtDttm, mapSheetAnalEntity.analStrtDttm,
mapSheetAnalEntity.analEndDttm, mapSheetAnalEntity.analEndDttm,
mapSheetAnalEntity.analSec, mapSheetAnalEntity.analSec,
mapSheetAnalEntity.analPredSec, mapSheetAnalEntity.analPredSec,
mapSheetAnalEntity.analState, mapSheetAnalEntity.analState,
Expressions.stringTemplate( Expressions.stringTemplate(
"fn_code_name({0}, {1})", "0002", mapSheetAnalEntity.analState), "fn_code_name({0}, {1})", "0002", mapSheetAnalEntity.analState),
mapSheetAnalEntity.gukyuinUsed)) mapSheetAnalEntity.gukyuinUsed))
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.where(builder) .where(builder)
.offset(pageable.getOffset()) .offset(pageable.getOffset())
.limit(pageable.getPageSize()) .limit(pageable.getPageSize())
.orderBy(mapSheetAnalEntity.id.desc()) .orderBy(mapSheetAnalEntity.id.desc())
.fetch(); .fetch();
long total = long total =
queryFactory queryFactory
.select(mapSheetAnalEntity.id) .select(mapSheetAnalEntity.id)
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.where(builder) .where(builder)
.fetchCount(); .fetchCount();
return new PageImpl<>(content, pageable, total); return new PageImpl<>(content, pageable, total);
} }
@@ -112,41 +112,40 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
// 1. 최신 버전 UID를 가져오는 서브쿼리 // 1. 최신 버전 UID를 가져오는 서브쿼리
JPQLQuery<Long> latestVerUidSub = JPQLQuery<Long> latestVerUidSub =
JPAExpressions.select(tmv.id.max()).from(tmv).where(tmv.modelUid.eq(tmm.id)); JPAExpressions.select(tmv.id.max()).from(tmv).where(tmv.modelUid.eq(tmm.id));
Optional<InferenceResultDto.AnalResSummary> content = Optional<InferenceResultDto.AnalResSummary> content =
Optional.ofNullable( Optional.ofNullable(
queryFactory queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
InferenceResultDto.AnalResSummary.class, InferenceResultDto.AnalResSummary.class,
mapSheetAnalEntity.id, mapSheetAnalEntity.id,
mapSheetAnalEntity.analTitle, mapSheetAnalEntity.analTitle,
tmm.modelNm.concat(" ").concat(tmv.modelVer).as("modelInfo"), tmm.modelNm.concat(" ").concat(tmv.modelVer).as("modelInfo"),
mapSheetAnalEntity.targetYyyy, mapSheetAnalEntity.targetYyyy,
mapSheetAnalEntity.compareYyyy, mapSheetAnalEntity.compareYyyy,
mapSheetAnalEntity.analMapSheet, mapSheetAnalEntity.analMapSheet,
mapSheetAnalEntity.analStrtDttm, mapSheetAnalEntity.analStrtDttm,
mapSheetAnalEntity.analEndDttm, mapSheetAnalEntity.analEndDttm,
mapSheetAnalEntity.analSec, mapSheetAnalEntity.analSec,
mapSheetAnalEntity.analPredSec, mapSheetAnalEntity.analPredSec,
mapSheetAnalEntity.resultUrl, mapSheetAnalEntity.resultUrl,
mapSheetAnalEntity.detectingCnt, mapSheetAnalEntity.detectingCnt,
mapSheetAnalEntity.accuracy, mapSheetAnalEntity.accuracy,
mapSheetAnalEntity.analState, mapSheetAnalEntity.analState,
Expressions.stringTemplate( Expressions.stringTemplate(
"fn_code_name({0}, {1})", "0002", mapSheetAnalEntity.analState))) "fn_code_name({0}, {1})", "0002", mapSheetAnalEntity.analState)))
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.leftJoin(tmm) .leftJoin(tmm)
.on(mapSheetAnalEntity.modelUid.eq(tmm.id)) .on(mapSheetAnalEntity.modelUid.eq(tmm.id))
.leftJoin(tmv) .leftJoin(tmv)
.on(tmv.modelUid.eq(tmm.id).and(tmv.id.eq(latestVerUidSub))) .on(tmv.modelUid.eq(tmm.id).and(tmv.id.eq(latestVerUidSub)))
.where(mapSheetAnalEntity.id.eq(id)) .where(mapSheetAnalEntity.id.eq(id))
.fetchOne()); .fetchOne());
return content; return content;
} }
/** /**
* 분석결과 상세 class name별 탐지 개수 * 분석결과 상세 class name별 탐지 개수
* *
@@ -156,16 +155,16 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
@Override @Override
public List<Dashboard> getDashboard(Long id) { public List<Dashboard> getDashboard(Long id) {
return queryFactory return queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
Dashboard.class, Dashboard.class,
mapSheetAnalSttcEntity.id.classAfterCd, mapSheetAnalSttcEntity.id.classAfterCd,
mapSheetAnalSttcEntity.classAfterCnt.sum())) mapSheetAnalSttcEntity.classAfterCnt.sum()))
.from(mapSheetAnalSttcEntity) .from(mapSheetAnalSttcEntity)
.where(mapSheetAnalSttcEntity.id.analUid.eq(id)) .where(mapSheetAnalSttcEntity.id.analUid.eq(id))
.groupBy(mapSheetAnalSttcEntity.id.classAfterCd) .groupBy(mapSheetAnalSttcEntity.id.classAfterCd)
.orderBy(mapSheetAnalSttcEntity.id.classAfterCd.asc()) .orderBy(mapSheetAnalSttcEntity.id.classAfterCd.asc())
.fetch(); .fetch();
} }
@Override @Override
@@ -182,22 +181,22 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
*/ */
@Override @Override
public Page<MapSheetAnalDataGeomEntity> listInferenceResultWithGeom( public Page<MapSheetAnalDataGeomEntity> listInferenceResultWithGeom(
List<Long> ids, SearchGeoReq searchReq) { List<Long> ids, SearchGeoReq searchReq) {
// 분석 차수 // 분석 차수
QMapSheetAnalDataGeomEntity detectedEntity = QMapSheetAnalDataGeomEntity detectedEntity =
QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity;
Pageable pageable = searchReq.toPageable(); Pageable pageable = searchReq.toPageable();
// 검색조건 // 검색조건
JPAQuery<MapSheetAnalDataGeomEntity> query = JPAQuery<MapSheetAnalDataGeomEntity> query =
queryFactory queryFactory
.selectFrom(detectedEntity) .selectFrom(detectedEntity)
.where( .where(
detectedEntity.dataUid.in(ids), detectedEntity.dataUid.in(ids),
eqTargetClass(detectedEntity, searchReq.getTargetClass()), eqTargetClass(detectedEntity, searchReq.getTargetClass()),
eqCompareClass(detectedEntity, searchReq.getCompareClass()), eqCompareClass(detectedEntity, searchReq.getCompareClass()),
containsMapSheetNum(detectedEntity, searchReq.getMapSheetNum())); containsMapSheetNum(detectedEntity, searchReq.getMapSheetNum()));
// count // count
long total = query.fetchCount(); long total = query.fetchCount();
@@ -209,11 +208,11 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
} }
List<MapSheetAnalDataGeomEntity> content = List<MapSheetAnalDataGeomEntity> content =
query query
.offset(pageable.getOffset()) .offset(pageable.getOffset())
.limit(pageable.getPageSize()) .limit(pageable.getPageSize())
.orderBy(orders.toArray(new OrderSpecifier[0])) .orderBy(orders.toArray(new OrderSpecifier[0]))
.fetch(); .fetch();
return new PageImpl<>(content, pageable, total); return new PageImpl<>(content, pageable, total);
} }
@@ -235,19 +234,19 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
// 기준년도 분류 // 기준년도 분류
if (searchGeoReq.getTargetClass() != null && !searchGeoReq.getTargetClass().equals("")) { if (searchGeoReq.getTargetClass() != null && !searchGeoReq.getTargetClass().equals("")) {
builder.and( builder.and(
mapSheetAnalDataGeomEntity mapSheetAnalDataGeomEntity
.classAfterCd .classAfterCd
.toLowerCase() .toLowerCase()
.eq(searchGeoReq.getTargetClass().toLowerCase())); .eq(searchGeoReq.getTargetClass().toLowerCase()));
} }
// 비교년도 분류 // 비교년도 분류
if (searchGeoReq.getCompareClass() != null && !searchGeoReq.getCompareClass().equals("")) { if (searchGeoReq.getCompareClass() != null && !searchGeoReq.getCompareClass().equals("")) {
builder.and( builder.and(
mapSheetAnalDataGeomEntity mapSheetAnalDataGeomEntity
.classBeforeCd .classBeforeCd
.toLowerCase() .toLowerCase()
.eq(searchGeoReq.getCompareClass().toLowerCase())); .eq(searchGeoReq.getCompareClass().toLowerCase()));
} }
// 분석도엽 // 분석도엽
@@ -257,39 +256,39 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
} }
List<InferenceResultDto.Geom> content = List<InferenceResultDto.Geom> content =
queryFactory queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
InferenceResultDto.Geom.class, InferenceResultDto.Geom.class,
mapSheetAnalDataGeomEntity.compareYyyy, mapSheetAnalDataGeomEntity.compareYyyy,
mapSheetAnalDataGeomEntity.targetYyyy, mapSheetAnalDataGeomEntity.targetYyyy,
mapSheetAnalDataGeomEntity.classBeforeCd, mapSheetAnalDataGeomEntity.classBeforeCd,
mapSheetAnalDataGeomEntity.classBeforeProb, mapSheetAnalDataGeomEntity.classBeforeProb,
mapSheetAnalDataGeomEntity.classAfterCd, mapSheetAnalDataGeomEntity.classAfterCd,
mapSheetAnalDataGeomEntity.classAfterProb, mapSheetAnalDataGeomEntity.classAfterProb,
mapSheetAnalDataGeomEntity.mapSheetNum, mapSheetAnalDataGeomEntity.mapSheetNum,
mapSheetAnalDataGeomEntity.geom, mapSheetAnalDataGeomEntity.geom,
mapSheetAnalDataGeomEntity.geomCenter)) mapSheetAnalDataGeomEntity.geomCenter))
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.join(mapSheetAnalDataEntity) .join(mapSheetAnalDataEntity)
.on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id)) .on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id))
.join(mapSheetAnalDataGeomEntity) .join(mapSheetAnalDataGeomEntity)
.on(mapSheetAnalDataGeomEntity.dataUid.eq(mapSheetAnalDataEntity.id)) .on(mapSheetAnalDataGeomEntity.dataUid.eq(mapSheetAnalDataEntity.id))
.where(builder) .where(builder)
.offset(pageable.getOffset()) .offset(pageable.getOffset())
.limit(pageable.getPageSize()) .limit(pageable.getPageSize())
.fetch(); .fetch();
long total = long total =
queryFactory queryFactory
.select(mapSheetAnalDataGeomEntity.id) .select(mapSheetAnalDataGeomEntity.id)
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.join(mapSheetAnalDataEntity) .join(mapSheetAnalDataEntity)
.on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id)) .on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id))
.join(mapSheetAnalDataGeomEntity) .join(mapSheetAnalDataGeomEntity)
.on(mapSheetAnalDataGeomEntity.dataUid.eq(mapSheetAnalDataEntity.id)) .on(mapSheetAnalDataGeomEntity.dataUid.eq(mapSheetAnalDataEntity.id))
.where(builder) .where(builder)
.fetchCount(); .fetchCount();
return new PageImpl<>(content, pageable, total); return new PageImpl<>(content, pageable, total);
} }
@@ -303,18 +302,16 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
@Override @Override
public List<Long> getSheets(Long id) { public List<Long> getSheets(Long id) {
return queryFactory return queryFactory
.select(mapSheetAnalDataEntity.mapSheetNum) .select(mapSheetAnalDataEntity.mapSheetNum)
.from(mapSheetAnalEntity) .from(mapSheetAnalEntity)
.join(mapSheetAnalDataEntity) .join(mapSheetAnalDataEntity)
.on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id)) .on(mapSheetAnalDataEntity.analUid.eq(mapSheetAnalEntity.id))
.where(mapSheetAnalEntity.id.eq(id)) .where(mapSheetAnalEntity.id.eq(id))
.groupBy(mapSheetAnalDataEntity.mapSheetNum) .groupBy(mapSheetAnalDataEntity.mapSheetNum)
.fetch(); .fetch();
} }
/** /** Pageable의 Sort를 QueryDSL OrderSpecifier로 변환 */
* Pageable의 Sort를 QueryDSL OrderSpecifier로 변환
*/
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
private List<OrderSpecifier<?>> getOrderSpecifiers(Sort sort) { private List<OrderSpecifier<?>> getOrderSpecifiers(Sort sort) {
List<OrderSpecifier<?>> orders = new ArrayList<>(); List<OrderSpecifier<?>> orders = new ArrayList<>();
@@ -329,7 +326,8 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
// 유효한 필드만 처리 // 유효한 필드만 처리
switch (property) { switch (property) {
case "classBeforeCd" -> orders.add(new OrderSpecifier(direction, entity.classBeforeCd)); case "classBeforeCd" -> orders.add(new OrderSpecifier(direction, entity.classBeforeCd));
case "classBeforeProb" -> orders.add(new OrderSpecifier(direction, entity.classBeforeProb)); case "classBeforeProb" ->
orders.add(new OrderSpecifier(direction, entity.classBeforeProb));
case "classAfterCd" -> orders.add(new OrderSpecifier(direction, entity.classAfterCd)); case "classAfterCd" -> orders.add(new OrderSpecifier(direction, entity.classAfterCd));
case "classAfterProb" -> orders.add(new OrderSpecifier(direction, entity.classAfterProb)); case "classAfterProb" -> orders.add(new OrderSpecifier(direction, entity.classAfterProb));
case "mapSheetNum" -> orders.add(new OrderSpecifier(direction, entity.mapSheetNum)); case "mapSheetNum" -> orders.add(new OrderSpecifier(direction, entity.mapSheetNum));
@@ -338,9 +336,8 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
case "area" -> orders.add(new OrderSpecifier(direction, entity.area)); case "area" -> orders.add(new OrderSpecifier(direction, entity.area));
case "createdDttm" -> orders.add(new OrderSpecifier(direction, entity.createdDttm)); case "createdDttm" -> orders.add(new OrderSpecifier(direction, entity.createdDttm));
case "updatedDttm" -> orders.add(new OrderSpecifier(direction, entity.updatedDttm)); case "updatedDttm" -> orders.add(new OrderSpecifier(direction, entity.updatedDttm));
// 유효하지 않은 필드는 무시 // 유효하지 않은 필드는 무시
default -> { default -> {}
}
} }
} }
} }
@@ -349,21 +346,21 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
} }
private BooleanExpression eqTargetClass( private BooleanExpression eqTargetClass(
QMapSheetAnalDataGeomEntity detectedEntity, String targetClass) { QMapSheetAnalDataGeomEntity detectedEntity, String targetClass) {
return targetClass != null && !targetClass.isEmpty() return targetClass != null && !targetClass.isEmpty()
? detectedEntity.classAfterCd.toLowerCase().eq(targetClass.toLowerCase()) ? detectedEntity.classAfterCd.toLowerCase().eq(targetClass.toLowerCase())
: null; : null;
} }
private BooleanExpression eqCompareClass( private BooleanExpression eqCompareClass(
QMapSheetAnalDataGeomEntity detectedEntity, String compareClass) { QMapSheetAnalDataGeomEntity detectedEntity, String compareClass) {
return compareClass != null && !compareClass.isEmpty() return compareClass != null && !compareClass.isEmpty()
? detectedEntity.classBeforeCd.toLowerCase().eq(compareClass.toLowerCase()) ? detectedEntity.classBeforeCd.toLowerCase().eq(compareClass.toLowerCase())
: null; : null;
} }
private BooleanExpression containsMapSheetNum( private BooleanExpression containsMapSheetNum(
QMapSheetAnalDataGeomEntity detectedEntity, List<Long> mapSheet) { QMapSheetAnalDataGeomEntity detectedEntity, List<Long> mapSheet) {
if (mapSheet == null || mapSheet.isEmpty()) { if (mapSheet == null || mapSheet.isEmpty()) {
return null; return null;
} }

View File

@@ -21,13 +21,13 @@ public class TestApiController {
@Operation(summary = "admin test", description = "admin test api") @Operation(summary = "admin test", description = "admin test api")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "조회", description = "조회",
content = @Content(schema = @Schema(implementation = String.class))), content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse( @ApiResponse(
responseCode = "403", responseCode = "403",
description = "권한 없음", description = "권한 없음",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
@GetMapping("/admin") @GetMapping("/admin")
public String admin() { public String admin() {
@@ -37,13 +37,13 @@ public class TestApiController {
@Operation(summary = "label test", description = "label test api") @Operation(summary = "label test", description = "label test api")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "조회", description = "조회",
content = @Content(schema = @Schema(implementation = String.class))), content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse( @ApiResponse(
responseCode = "403", responseCode = "403",
description = "권한 없음", description = "권한 없음",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
@GetMapping("/label") @GetMapping("/label")
public String label() { public String label() {
@@ -53,13 +53,13 @@ public class TestApiController {
@Operation(summary = "review test", description = "review test api") @Operation(summary = "review test", description = "review test api")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "조회", description = "조회",
content = @Content(schema = @Schema(implementation = String.class))), content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse( @ApiResponse(
responseCode = "403", responseCode = "403",
description = "권한 없음", description = "권한 없음",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
@GetMapping("/review") @GetMapping("/review")
public String review() { public String review() {