Spring Boot JAR部署Docker时出现H2 SQL语法错误问题
我有一个Spring Boot项目,本地使用MySQL数据库,仅测试环境使用H2数据库。项目本地编译、启动均正常,但将JAR包通过Dockerfile打包到容器后启动时,出现异常:明明生产环境未启用H2,却触发了H2的SQL语法错误。Flyway执行迁移时,在创建Quartz的QRTZ_JOB_DETAILS表的语句处报错,错误信息如下:
Error; (Works in mysql on app startup and is a generic quartz copy paste configuration)
2023-02-23T04:42:07.489897039Z Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "CREATE TABLE QRTZ_JOB_DETAILS\000d\000a(\000d\000a SCHED_NAME VARCHAR(120) NOT NULL,\000d\000a JOB_NAME VARCHAR(200) NOT NULL,\000d\000a JOB_GROUP VARCHAR(200) NOT NULL,\000d\000a DESCRIPTION VARCHAR(250) NULL,\000d\000a JOB_CLASS_NAME VARCHAR(250) NOT NULL,\000d\000a IS_DURABLE BOOLEAN NOT NULL,\000d\000a IS_NONCONCURRENT BOOLEAN NOT NULL,\000d\000a IS_UPDATE_DATA BOOLEAN NOT NULL,\000d\000a REQUESTS_RECOVERY BOOLEAN NOT NULL,\000d\000a JOB_DATA BLOB NULL,\000d\000a PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)\000d\000a) ENGINE[*]=InnoDB"; expected "identifier"; SQL statement:
已尝试以下操作但未解决:
- 清理构建产物
- 指定H2方言
项目配置文件及Dockerfile
application.properties
spring.jpa.hibernate.ddl-auto=validate spring.flyway.enabled=true spring.flyway.baseline-on-migrate=true spring.flyway.table=flyway_order_schema_history #spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/cf?enabledTLSProtocols=TLSv1.2&useSSL=false&useServerPrepStmts=true spring.datasource.url=jdbc:mysql://docker.for.win.localhost:3306/cf?enabledTLSProtocols=TLSv1.2&useSSL=false&useServerPrepStmts=true spring.jpa.database=mysql spring.profiles.include=quartz spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true logging.level.org.hibernate.SQL=debug logging.level.org.hibernate.type.descriptor.sql=trace server.port=8020 management.server.port=8029
application-test.properties
spring.main.allow-bean-definition-overriding=true spring.application.name="cf-ms-test-runner" spring.data.jpa.repositories.enabled=true spring.profiles.active=test spring.flyway.enabled=false spring.jpa.hibernate.ddl-auto=create server.servlet.context-path=/api/v1 spring.jpa.database=H2 spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER spring.jackson.default-property-inclusion=NON_NULL spring.datasource.driverClassName=org.h2.Driver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.datasource.url=jdbc:h2:mem:skel;MODE=MySQL;IGNORECASE=TRUE spring.datasource.username=sa spring.datasource.password=
Dockerfile
FROM openjdk:11.0.11-jre VOLUME /tmp COPY build/libs/*.jar app.jar ENTRYPOINT ["java","-jar","app.jar"]
问题根源
容器启动时,项目意外加载了H2数据库驱动或配置,导致Flyway用H2执行了MySQL语法的SQL(比如ENGINE=InnoDB是MySQL专属语法,H2不支持)。
解决步骤
显式指定生产环境配置启动容器
Docker默认加载application.properties,但可能存在配置优先级问题,启动时显式指定环境:docker run -e SPRING_PROFILES_ACTIVE=prod your-image-name若未定义
prod配置,确保application.properties完全指向MySQL,无任何H2相关依赖或配置。限制H2依赖仅在测试环境生效
确保H2依赖仅在testscope下引入,避免打包到生产JAR:<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>testImplementation 'com.h2database:h2'修正测试环境配置冲突
application-test.properties中同时指定MySQL方言和H2驱动,存在冲突,修改为:spring.jpa.database-platform=org.hibernate.dialect.H2Dialect检查容器启动时的环境变量
确认Docker启动脚本或docker-compose.yml中未设置SPRING_PROFILES_ACTIVE=test,如有则移除。清理Docker镜像缓存
重新构建镜像,避免旧缓存影响:docker build --no-cache -t your-image-name .
内容的提问来源于stack exchange,提问作者User Unknown

