You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置Spring Boot测试用H2、运行用MySQL及解决构建错误

问题与解决方案:Spring Boot测试环境H2配置及MySQL方言错误修复

问题背景

使用Java Spring Boot搭建微服务,部署在Docker容器中,运行环境连接本地MySQL数据库,单元测试希望用H2内存数据库降低开销。涉及build.gradle、application.properties、application-test.properties和Dockerfile等配置文件,但构建时出现错误。

错误日志

java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@44976b08 testClass = com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplicationTests, locations = [], classes = [com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@5023bb8b, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@604f2bd2, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@30b19518, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@62e20a76, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@28e8dde3, org.springframework.boot.test.web.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@59252cb6, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@cc9a5aaa], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)
<snip>  
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
<snip>  
    at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
    ... 19 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
<snip>  
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798)
    ... 39 more
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:154)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:236)
<snip>  
    at app//org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
    ... 54 more
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [org.hibernate.dialect.MySQL5Dialect]
    at app//org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:126)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:150)
    ... 64 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.dialect.MySQL5Dialect
    at org.hibernate.boot.registry.classloading.internal.AggregatedClassLoader.findClass(AggregatedClassLoader.java:216)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:123)
    ... 65 more

当前配置文件

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.4.0'
    id 'io.spring.dependency-management' version '1.1.6'
    id 'application'
}

application {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

bootJar {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

group = 'com.apptraqer'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // Spring Boot Starters
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // OAuth2 and Security Enhancements
    implementation 'org.springframework.security:spring-security-oauth2-jose'

    // JSON Web Token (JJWT)
    implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-orgjson:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

    // Database Connector
    runtimeOnly  'mysql:mysql-connector-java:8.0.26'

    // Testing Dependencies
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'com.h2database:h2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    implementation 'javax.persistence:javax.persistence-api:2.2'
    implementation 'javax.xml.bind:jaxb-api:2.3.1'
}

tasks.named('test') {
    useJUnitPlatform()
}

tasks.withType(JavaCompile) {
    options.compilerArgs << "-Xlint:deprecation"
}

application.properties

# application.properties (Common Settings for All Environments)

# Application Name and Port (could be overridden per environment if needed)
spring.application.name=apptraqer-auth-service
server.port=8081

# Database Configuration (default to MySQL for non-test environments)
spring.datasource.url=jdbc:mysql://apptraqer-mysql:3306/apptraqerdata
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Hibernate/JPA Settings (should be the same across all environments)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

application-test.properties

# application-test.properties (Test Environment Overrides)

# Override Database Configuration for Test with H2 (or whatever you use in tests)
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

#H2 settings
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

Dockerfile

FROM openjdk:17-jdk-slim as build

WORKDIR /app

COPY build.gradle settings.gradle ./

COPY gradlew ./
COPY gradle/wrapper/ ./gradle/wrapper/

ENV SPRING_PROFILES_ACTIVE=test

RUN ./gradlew build --no-daemon

COPY src ./src

RUN ./gradlew build

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY --from=build /app/build/libs/apptraqer-auth-service.jar apptraqer-auth-service.jar

EXPOSE 8081

CMD ["java", "-jar", "apptraqer-auth-service.jar"]

解决方案

1. 修复MySQL方言版本问题

Spring Boot 3.4.0对应的Hibernate版本已移除MySQL5Dialect,改用适配MySQL 8.0+的MySQL8Dialect。修改application.properties中的方言配置:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

2. 激活测试环境Profile

在测试类上添加@ActiveProfiles("test")注解,确保单元测试时加载application-test.properties的H2配置:

@SpringBootTest
@ActiveProfiles("test")
class ApptraqerAuthServiceApplicationTests {
    // 测试代码
}

3. 调整Dockerfile构建逻辑

构建阶段无需激活test profile,移除ENV SPRING_PROFILES_ACTIVE=test,并优化构建步骤避免重复执行build:

FROM openjdk:17-jdk-slim as build

WORKDIR /app

COPY gradlew ./
COPY gradle/wrapper/ ./gradle/wrapper/
COPY build.gradle settings.gradle ./

# 下载依赖(依赖不变时可缓存)
RUN ./gradlew dependencies --no-daemon

COPY src ./src

# 构建jar包,跳过测试(如需跑测试可去掉-x test)
RUN ./gradlew bootJar -x test --no-daemon

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY --from=build /app/build/libs/apptraqer-auth-service.jar apptraqer-auth-service.jar

EXPOSE 8081

# 运行时默认使用生产环境配置,如需测试环境可在此添加ENV SPRING_PROFILES_ACTIVE=test
CMD ["java", "-jar", "apptraqer-auth-service.jar"]

4. 优化依赖配置

移除冲突/冗余依赖:javax.persistence:javax.persistence-api和javax.xml.bind:jaxb-api,Spring Boot Starter已包含对应Jakarta版本的依赖,避免版本冲突:

dependencies {
    // Spring Boot Starters
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // OAuth2 and Security Enhancements
    implementation 'org.springframework.security:spring-security-oauth2-jose'

    // JSON Web Token (JJWT)
    implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-orgjson:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

    // Database Connector
    runtimeOnly  'mysql:mysql-connector-java:8.0.26'

    // Testing Dependencies
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'com.h2database:h2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

验证修改

  • 执行单元测试:./gradlew test,确认H2数据库正常加载,无方言错误。
  • 构建Docker镜像:docker build -t apptraqer-auth-service .,运行容器时通过环境变量传入MySQL账号密码,验证生产环境连接正常。

内容的提问来源于stack exchange,提问作者Sam Carleton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:07:01