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

Java 20中调用JDBI.open获取SqlObject Dao实例报错求助

问题原因分析

报错的核心是Java模块系统的访问限制:JDBI 2.x版本依赖的cglib库使用反射调用java.lang.ClassLoader.defineClass方法,但Java 20的模块系统默认不允许未命名模块(你的应用代码和依赖库所在的模块)访问java.lang包的内部方法,导致InaccessibleObjectException。

JDBI 2.78是2017年的旧版本,其依赖的cglib版本未适配Java 9及以上的模块系统,因此在Java 20中无法正常生成SqlObject代理类。


解决方案

方案1:升级到JDBI 3.x(推荐)

JDBI 3.x彻底替换了cglib为ByteBuddy,完全兼容Java 9+的模块系统,同时提供更多新特性和长期支持。

步骤1:更新pom.xml依赖

替换原JDBI依赖为3.x版本:

<dependency>
    <groupId>org.jdbi.v3</groupId>
    <artifactId>jdbi3-core</artifactId>
    <version>3.38.1</version> <!-- 可替换为最新稳定版 -->
</dependency>
<dependency>
    <groupId>org.jdbi.v3</groupId>
    <artifactId>jdbi3-sqlobject</artifactId>
    <version>3.38.1</version>
</dependency>

步骤2:调整代码中的导入路径

JDBI 3.x的包名从org.skife.jdbi.v2改为org.jdbi.v3,需要更新相关导入:

// 替换原DBI导入
import org.jdbi.v3.core.DBI;
// 替换Dao注解导入
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.result.SingleValueResult;

步骤3:验证代码逻辑

JDBI 3.x的open方法用法基本兼容,但推荐使用更优雅的资源管理方式:

try (MyDao myDao = dbi.onDemand(MyDao.class)) {
    int id = myDao.getObjectId();
    System.out.println("got id:" + id);
}

(onDemand方法会自动管理连接生命周期,比open更简洁)


方案2:添加JVM启动参数(临时 workaround)

如果暂时无法升级JDBI,可以通过JVM参数放宽模块系统限制,允许未命名模块访问java.lang包:

--add-opens java.base/java.lang=ALL-UNNAMED

在IDE中配置:

  • IntelliJ IDEA:Run Configuration → VM options中添加上述参数
  • Eclipse:Run Configurations → Arguments → VM arguments中添加

命令行运行:

java --add-opens java.base/java.lang=ALL-UNNAMED -jar your-application.jar

⚠️ 注意:此方案仅作为临时解决办法,不推荐用于生产环境,因为它绕过了Java模块系统的安全限制。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:05:18