[JPA] Native 쿼리 사용 및 오류

방패맨·2023년 12월 1일
post-thumbnail

대시보드에 표현할 통계 데이터를 가져오는 쿼리를 짜야했다.
무수히 긴 쿼리와 많은 join( 잦은 JOIN사용은 DB성능에 좋지않다. 추후 SQL튜닝에 대해 다룰예정!) 을 사용 해야해서 queryDsl을 사용하려 했다. 하지만 쿼리에서 뷰를 사용하는데 queryDsl은 인라인 뷰를 지원하지 않는다. 이에 대해 2가지 방법을 고려하였다.

1.SubQuery 사용

repository에서 서브쿼리 , @subselect을 이용하여 queryDsl에서 만든 뷰를 entity처럼 사용하기

예시

@Data
@Entity
@Immutable
@Subselect(
   "SELECT SHIELDNM FROM SHIELDTABLE
 WHERE SHIELDCOLOR ='RED'"
)
@Synchronize({"ShieldTable"})
public class ShieldTableView implements Serializable {

  @Id
  @Column(name = "SHIELD_NM")
  @Schema(description = "방패 이름", nullable = false)
  private String shieldNm; 
  ...
}

하지만 @subselect 어노테이션을 사용한 쿼리가 자체가 성능이 매우 안좋은 쿼리이고 다시 또 querydsl에서 사용하게된다면 더욱 좋지않다. 트래픽이 많은 서비스에서는 지양하는게 좋다.

2.JPQL 사용

repository에서 @query 어노테이션을 사용하여 native 쿼리를 이용. 동적으로 받아야할 값들은 @Param으로 받기

예시

public interface ShieldTableRepository 
extends JpaRepository<ShieldTable>,
    QuerydslPredicateExecutor<ShieldTable> {
 @Query(value = "SELECT SHIELDNM FROM SHIELDTABLE
 WHERE SHIELDCOLOR = :shieldColor  nativeQuery = true)
  List<Shield> findByShildNm(
  @Param("shieldColor") String shieldColor);
  ...

위 2가지 방법중 성능과 특정 기간동안의
통계 데이터를 가져오는 것(동적으로 날짜값을 사용해야하므로) 을 고려하여
2번을 선택하였다.

3. 문제 발생

[WARN]org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions (SqlExceptionHelper.java:137) - SQL Error: 1861, SQLState: 22008
(ORA-01861: 리터럴이 형식 문자열과 일치하지 않음 )

로컬환경에서는 문제가 없이 쿼리를 수행하고데이터를 잘 가져왔다.
하지만 개발배포 이후 개발환경에서 문제가 발생!
이에 대하여 검색한 결과
OS의 Lang설정이 달라 문자 열을 묵시적으로 날짜로 변환을 못해서 발생하는 오류 였다.
OS 환경변수인 NLS_LANG 설정에 영향을 받으므로 모든 애플리케이션 서버의 LANG을 세팅해주는 방법도 있었지만 번거로우므로
쿼리에서 모두 날짜형식을 지정해주는 방법을 택하였다.

예시

SELECT SHIELDNM 
FROM SHIELDTABLE B
LEFTJOIN (SELECT TO_CHAR(MAKEDT,'YYYY/MM/DD') AS MAKEDT
FROM SHILEDTABLE) A
ON A.MAKEDT= B.REPAIRDT 

에서

ON A.MAKEDT= B.REPAIRDT // X
ON A.TO_CHAR(MAKEDT,'YYYY/MM/DD')= B.REPAIRDT // 날짜 형식 지정

으로 바꿔주니 정상적으로 쿼리가 수행되었다.

profile
개발자 방패맨의 기술블로그

0개의 댓글