Lewis's Tech Keep

[Spring] h2를 이용한 테스트 시 user 테이블 테스트를 실패했을 때 확인 본문

JAVA/Spring

[Spring] h2를 이용한 테스트 시 user 테이블 테스트를 실패했을 때 확인

Lewis Seo 2023. 4. 25. 23:55

계기


Spring으로 user 관련 서비스를 만들다 DataJpaTest를 통한 테스트 코드 운용 중에 에러를 발생!

 

 

에러 메시지


o.h.e.internal.DefaultLoadEventListener  : HHH000327: Error performing load command

org.hibernate.exception.SQLGrammarException: could not prepare statement
	at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:151) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:2122) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2059) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2037) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
	at org.hibernate.loader.Loader.doQuery(Loader.java:956) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]

 

위와 같은 그림의 에러 메시지와 함께 내리다보면

 

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "select user0_.user_id as user_id1_0_0_, user0_.user_name as user_nam2_0_0_ from [*]user user0_ where user0_.user_id=?"; expected "identifier"; SQL statement:
select user0_.user_id as user_id1_0_0_, user0_.user_name as user_nam2_0_0_ from user user0_ where user0_.user_id=? [42001-214]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:502) ~[h2-2.1.214.jar:2.1.214]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) ~[h2-2.1.214.jar:2.1.214]

이런 에러메시지가 있다.

 

Syntax error기 때문에 문법오류라고 생각하여 무엇을 잘못했는지 찾아보다가 발견한 것 -> 링크

 

USER 테이블 생성이 안됩니다. - 인프런 | 질문 & 답변

AUTHORITY, USER_AUTHORITY 테이블은 제대로 생성이 되는데, USER 테이블만 생성이 되지 않습니다.     - 질문 & 답변 | 인프런

www.inflearn.com

 

원인


테스트를 쓰면 기본으로 h2 를 쓰게 되는데 이 중 2.1.212 버전에서는 user는 예약어다. [링크] (Reserved Words 로 검색)

예약어를 테이블 이름으로 썼기에 나는 문법 에러였다.

 

 

 

해결방법


1. h2 버전 다운 그레이드 -> 예약어 user 가 걸려있지 않은 버전으로 다운 그레이드

  • 추천하고 싶지는 않다. 버전을 계속 신경 써 줘야 하기 때문

 

2. yml 파일에 설정할 경우 NON_KEYWORDS 에 예약어 USER를 추가하여 방지

  • 이 경우 어떻게 되는 지에 대한 링크
  • 어떻게 하는 지 : 아래와 같이 설정 후 테스트 파일로 이동
spring:
  datasource:
    url: jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1;NON_KEYWORDS=USER
  • 테스트 파일로 이동 후 @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 설정
    • 설정하지 않을 경우 자동으로 DataJpaTest의 다른 설정이 덮어버려서 NON_KEYWORDS가 먹히지 않았다.
      • 아마 datasource.url을 다른 것으로 덮어버리는 것으로 추정하고 있다.
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@DataJpaTest
@Import(UserService.class)
class UserServiceTest {
}

 

3. quoted identifiers 를 사용

  • 옵션을 열어준다. 이 경우에 대한 링크
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true
  • 테스트 파일에서 다른 설정을 할 필요 없이 true로 열렸기 때문에 바로 작동

 

4. 예약어 피하기

  • 애초에 user가 예약어라면 피하는 것이 가장 좋지 않을까라는 생각도 하였다.
    • ex) user -> player 
    • user -> users 로 변경도 가능하지만 데이터 테이블 자체를 하나의 집합으로 본다면 복수형 테이블 이름은 자제하고 싶다.

 


 

 

user라는 테이블은 많은 개발자들이 사용하는 테이블 네이밍이라 생각되는데,
딱히 user가 아닌 다른 단어로 바꾸는 것도 난감하고, 억지로 복수형을 주고 싶지도 않아 많이 찾아보게 되었다. 

h2의 특이한 예약어라 생각이 되는데 참 재밌는 발견이다.

 

Comments