트러블슈팅

[오류를 잡아보자] NoClassDefFoundError / ClassNotFoundException: org.hibernate.dialect.MySQL57Dialect

ppusda 2024. 1. 28. 02:18

뭔가 어떻게든 된다.

문제

java.lang.NoClassDefFoundError: org/hibernate/dialect/MySQL57Dialect

최근에 개인 프로젝트 리팩토링을 진행하면서 스프링 부트 버전(2.5.93.2.1)을 업그레이드 하면서 발생하게 되었다.

단순히 Run만 하더라도 발생하게 되었으며, 이미 Github에서 관련 Issue가 다뤄진 적이 있어 정리해두려고 한다.


원인

Spring Boot 3.2.1 버전 부터 명시적인 Dialect 설정을 했을 시 발생하게 되는 문제이다.

Spring Boot는 JPA Provider가 적절한 Dialect를 찾아내게 하는 책임을 가지도록 하였으나, 이를 명시적으로 지정하게 되면서 발생하게 된 것이다.

하지만 프로젝트를 진행하면서 이를 명시적으로 지정했던 기억이 없어 관련 부분을 찾아보게 되었고, 문제가 된 부분은 아래와 같음을 알게되었다.

spring:
    jpa:
        hibernate:
          naming:
            implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
            physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        properties:
          hibernate:
            format_sql: true
            show_sql: true
        database: mysql

위 부분은 프로젝트 application.yml 에서의 JPA 관련 내용을 설정하는 부분이고,

그 중 spring.jpa.database: mysql 부분이 JPA가 Dialect를 명시적으로 설정하도록 하여 문제가 발생한 것이었다.


해결

Dialect 설정 제거

아래와 같이 dialect 설정을 한 부분이 있다면 제거하면 된다.

spring:
    jpa:
        database: mysql
-----------------------
spring:
    jpa:
        properties:
            hibernate:
                dialect: "org.hibernate.dialect.MySQL5Dialect"

필자의 경우는 jpa.database: mysql을 지운 후에 정상적으로 작동하는 것을 확인했다.

HibernateJpaVendorAdapter 추가 설정

Hibernate에 Config 설정을 추가로 설정해주면 해결할 수 있다.

@Configuration
public class HibernateConfig {

    private static final HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();

    @Bean
    public HibernateJpaVendorAdapter hibernateJpaVendorAdapter() {
        hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
        return hibernateJpaVendorAdapter;
    }

}

이는 Dialect 설정에 문제가 발생한 내용이기에 이를 설정하는 HibernateJpaVendorAdapter 에Database Platform을 설정해줌으로써 해결할 수 있다.

Spring boot 버전 다운그레이드

물론 이는 3.2.1 버전 부터 발생한 이슈로써 버전을 낮추면 정상적으로 작동한다.

id 'org.springframework.boot' version '3.2.0'

3.2.0 버전까지는 정상적으로 동작함을 확인하였다.


결론

위에서 한 번 언급했던 내용인데, Spring boot는 Jpa Provider가 Dialect 자동으로 설정할 수 있도록 하는 것을 권장하고 있다.

그렇기에 설정을 하지 않아도 정상적으로 작동하며, Spring boot가 원하는 바에 따를 수 있다.

꼭 필요한 경우가 있을지는 모르겠지만 아니라면 이를 굳이 명시할 필요가 없다.


참고