Spring Boot 3 默认不兼容 Oracle 12c 及更早 JDBC 驱动,需使用 ojdbc8+(runtime scope)、显式配置 oracle.liquibase.driver、采用标准 thin URL 格式、单 changeSet 单操作、扩展 DATABASECHANGELOG.FILENAME 长度。

Spring Boot 3 默认不兼容 Oracle 12c 及更早版本的 JDBC 驱动,直接启用 Liquibase 很可能在启动时抛出 java.lang.NoClassDefFoundError: oracle/jdbc/OracleType 或 liquibase.exception.DatabaseException: Cannot load database driver: oracle.jdbc.OracleDriver —— 根本原因不是 Liquibase 配置错,而是驱动类加载失败或版本不匹配。
Oracle 驱动必须用 ojdbc8+ 且显式声明 scope
Liquibase 在 Spring Boot 3 下依赖 Jakarta EE 9+(即 jakarta.* 命名空间),而旧版 ojdbc6.jar 或 ojdbc7.jar 仍使用 javax.*,会导致 ClassLoader 冲突。即使你用的是 Oracle 19c/21c,也必须用 ojdbc8 或更新版本(如 ojdbc11)。
关键操作:
- 删掉项目里所有
ojdbc6、ojdbc7依赖 - Maven 中声明
ojdbc8并设scope为runtime(Liquibase 不需要编译期 Oracle API):<dependency><groupid>com.oracle.database.jdbc</groupid><artifactid>ojdbc8</artifactid><scope>runtime</scope></dependency>
- 确认你的 Oracle 数据库版本与驱动兼容:ojdbc8 支持 Oracle 12.1+,ojdbc11 支持 18c+;不要混用
application.yml 中必须显式指定 oracle.liquibase.driver
Spring Boot 3 的自动配置对 Oracle 的 JDBC URL 解析不如 H2/PostgreSQL 稳定,spring.liquibase.driver-class-name 容易被忽略或覆盖。最稳妥方式是直接配 oracle.liquibase.driver(注意不是 spring.liquibase.driver-class-name)。
示例配置:
spring:
datasource:
url: jdbc:oracle:thin:@//localhost:1521/XEPDB1
username: myapp
password: secret
driver-class-name: oracle.jdbc.driver.OracleDriver
oracle:
liquibase:
driver: oracle.jdbc.driver.OracleDriver
说明:
-
driver-class-name是给 Spring JDBC 用的,oracle.liquibase.driver是 Liquibase 自己读取的(Liquibase 4.20+ 对 Oracle 有专用适配逻辑) - URL 必须用
jdbc:oracle:thin:@//host:port/SID或jdbc:oracle:thin:@//host:port/service_name格式;避免老式@host:port:SID冒号分隔写法,否则 Liquibase 会解析失败 - 如果使用 Oracle RAC 或连接池(如 UCP),需额外配
oracle.liquibase.connection-properties
changelog 文件里避免 use of Oracle-specific DDL without preConditions
Oracle 对 DDL 事务支持有限(比如 CREATE TABLE 会隐式提交),Liquibase 的默认事务行为在 Oracle 上容易导致部分执行后中断、状态不一致。别指望一个 changeSet 里混合 createTable + addForeignKeyConstraint 就能原子回滚。
安全做法:
- 每个
changeSet只做一件事:建表、加字段、建索引、插数据,分开写 - 对关键对象(如已存在表)加
<pre class="brush:php;toolbar:false;" conditions></pre>,例如:<pre class="brush:php;toolbar:false;" conditions onfail="MARK_RAN"> <not><tableexists tablename="EMPLOYEE"></tableexists></not>
- 慎用
sqlFile执行 PL/SQL 块;若必须用,确保文件以/结尾(Oracle SQL*Plus 兼容要求),并在sqlFile标签中设splitStatements: true和endDelimiter: /
DATABASECHANGELOG 表字段长度在 Oracle 下需手动调大
Liquibase 默认建的 DATABASECHANGELOG 表中 FILENAME 字段是 VARCHAR2(255),但 Spring Boot 3 + Maven 多模块项目生成的完整路径(如 liquibase/changelogs/module-user/v20240915_add_dept_id.sql)很容易超长,Oracle 插入时直接报 ORA-12899: value too large for column。
解决方法只有两种:
- 启动前手动执行:
ALTER TABLE DATABASECHANGELOG MODIFY FILENAME VARCHAR2(500);
- 或在第一个
changeSet里用sql标签提前改(但要注意该 changeSet 必须在 Liquibase 初始化前运行,通常需配合contexts和自定义初始化逻辑)
这个坑不会在日志里明确提示“filename too long”,只会卡在 Unexpected error running Liquibase 后面跟一串 Oracle 错误码,排查时要盯住 DATABASECHANGELOG 表结构和实际插入值长度。











