Java 8迁移至Java 19时RowSet相关访问错误求助
解决Java 19中无法访问com.sun.rowset.CachedRowSetImpl的问题
问题原因
Java 9引入的模块系统(JPMS)对内部API的访问做了严格限制,java.sql.rowset模块并未将com.sun.rowset包导出给应用模块(或未命名模块),而CachedRowSetImpl是该包下的内部实现类,直接依赖它会触发访问权限错误。
解决方案
方案1:使用标准JDBC RowSet API(推荐)
JDBC提供了RowSetProvider工厂类来创建标准的CachedRowSet实例,避免直接依赖Sun的内部实现,这是符合规范且跨版本兼容的做法。
修改代码步骤:
- 删除
import com.sun.rowset.CachedRowSetImpl;语句 - 将变量声明
CachedRowSetImpl crs = null;改为CachedRowSet crs = null; - 替换实例化代码
crs = new CachedRowSetImpl();为工厂方法创建实例
修改后的完整代码:
import javax.sql.rowset.*; import java.sql.*; import javax.sql.rowset.CachedRowSet; public static ResultSet dbExecuteQuery(String queryStmt) throws SQLException, ClassNotFoundException { Statement stmt = null; ResultSet resultSet = null; CachedRowSet crs = null; try { dbConnect(); System.out.println("Select statement: " + queryStmt + "\n"); stmt = conn.createStatement(); resultSet = stmt.executeQuery(queryStmt); // 使用标准工厂创建CachedRowSet crs = RowSetProvider.newFactory().createCachedRowSet(); crs.populate(resultSet); } catch (SQLException e) { System.out.println("Problem occurred at executeQuery operation : " + e); throw e; } finally { if (resultSet != null) { resultSet.close(); } if (stmt != null) { stmt.close(); } dbDisconnect(); } return crs; }
方案2:通过JVM参数临时开放访问(不推荐)
如果因特殊原因必须使用CachedRowSetImpl,可以通过JVM启动参数强制导出内部包,但这种方式依赖未公开的API,后续Java版本可能移除该类,存在兼容性风险:
- 如果你的应用是未模块化的(没有
module-info.java),添加启动参数:--add-exports java.sql.rowset/com.sun.rowset=ALL-UNNAMED - 如果你的应用是模块化的,将
ALL-UNNAMED替换为你的模块名:--add-exports java.sql.rowset/com.sun.rowset=你的模块名
总结
优先选择方案1,使用标准API确保代码的稳定性和兼容性,避免依赖Java内部实现类。
内容的提问来源于stack exchange,提问作者user20913388
相关产品推荐
相关产品推荐

