Gradle构建与IntelliJ执行时DuplicateKeyException包装行为不一致问题
我有一段执行Spring DatabaseClient插入逻辑的代码:
suspend fun saveXXX(xxx: XXX): InsertStatus { return try { doSave(xxx) InsertStatus.INSERTED } catch (exception: DuplicateKeyException) { val errDetails = (exception.cause as PostgresqlException).errorDetails if (errDetails.code == "23505") { val constraintName = errDetails.constraintName.get() if (constraintName == "unique_1") { return InsertStatus.DUPLICATE_1 } else if (constraintName == "unique_2") { return InsertStatus.DUPLICATE_2 } } return InsertStatus.UNKNOWN_ERROR } } private suspend fun doSave(xxx: XXX) { databaseClient .sql( """ SOME SQL """.trimIndent(), ).bind(...) .rowsUpdated() .awaitSingle() }
遇到的问题:在IntelliJ IDE中执行时,这段代码表现符合预期,exception.cause是PostgresqlException的子类;但通过./gradlew clean build命令执行Gradle构建时,exception.cause被另一个DuplicateKeyException包裹,即原本应为DuplicateKeyException(PostgresqlException)的异常实际变为DuplicateKeyException(DuplicateKeyException(PostgresqlException)),且该问题仅在Gradle运行时出现。请问这可能是什么原因导致的?
依赖版本/类路径差异
IDE运行时和Gradle构建时可能加载了不同版本的Spring Data R2DBC或PostgreSQL驱动依赖。部分版本的Spring Data R2DBC会对PostgreSQL的唯一约束异常额外包装一层DuplicateKeyException,而IDE可能因依赖缓存未更新,使用了异常包装逻辑不同的旧版本依赖,导致行为不一致。Gradle守护进程的类加载策略差异
Gradle构建默认使用自身的守护进程,其类加载器的依赖解析逻辑和IDE不同,可能出现依赖冲突(比如同时加载多个版本的Spring相关jar包),触发异常包装逻辑重复执行,最终导致异常被多层嵌套。测试配置与主代码依赖不一致
如果问题出现在Gradle测试任务中,可能测试配置里引入了额外的Spring异常处理组件或拦截器,这些组件在测试环境中二次包装了异常,而IDE运行测试时未加载这些额外依赖。字节码增强插件的影响
部分Gradle插件(如Spring Boot AOP插件、字节码修改插件)会在构建过程中修改代码字节码,改变了异常抛出的逻辑;而IDE运行时通常不会应用这些编译时增强,因此出现异常嵌套层级的差异。
内容的提问来源于stack exchange,提问作者ashur

