Java代码中添加多JDBC驱动Jar包解决KO16MSWIN949字符集错误
解决JDBC连接Oracle时KO16MSWIN949编码不支持问题(代码加载多Jar包)
问题核心
使用ojdbc11.jar连接Oracle数据库时,抛出Unsupported character set (add orai18n.jar to classpath): KO16MSWIN949错误,需通过代码动态加载ojdbc11.jar和orai18n.jar两个Jar包,无需在IDE中配置依赖。
解决方案
通过调整代码实现多Jar包动态加载,核心修改点如下:
- 允许
ConnectionDescription存储多个Jar包路径 - 让类加载器同时加载ojdbc11.jar和orai18n.jar
- 更新Jar路径配置,加入orai18n.jar的路径
修改后的完整代码
DBConnInfo.java
public class DBConnInfo { public ConnectionDescription getConnectionDescription() { ConnectionDescription connectionDesc = new ConnectionDescription(); connectionDesc.setUrl("jdbc:oracle:thin:@localhost:1521:xe"); connectionDesc.setUser("docker"); connectionDesc.setPassword("docker"); // 同时配置ojdbc11.jar和orai18n.jar的本地路径 connectionDesc.setDriverJarPaths(List.of( "/Users/elvis/JDBC/Oracle/ojdbc8-full/ojdbc11.jar", "/Users/elvis/JDBC/Oracle/ojdbc8-full/orai18n.jar" )); connectionDesc.setDriverClassName("oracle.jdbc.OracleDriver"); return connectionDesc; } public void executeSampleQuery(Connection conn) { try { Statement statement = conn.createStatement(); ResultSet rs = null; String sql = "SELECT UU.USERNAME \n" + "FROM USER_USERS UU"; rs = statement.executeQuery(sql); if(rs.next()) { System.out.println(rs.getString("USERNAME")); } } catch (Exception e) { e.printStackTrace(); } } }
ConnectionDescription.java
import java.util.List; import java.util.Properties; public class ConnectionDescription { private String url; private String user; private String password; private List<String> driverJarPaths; // 修改为集合类型,支持多个Jar路径 private String driverClassName; public ConnectionDescription() { } public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } public String getUser() { return this.user; } public void setUser(String user) { this.user = user; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public List<String> getDriverJarPaths() { return this.driverJarPaths; } public void setDriverJarPaths(List<String> driverJarPaths) { this.driverJarPaths = driverJarPaths; } public String getDriverClassName() { return this.driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public Properties getConnectionProperties() { Properties prop = new Properties(); prop.setProperty("user", this.user); prop.setProperty("password", this.password); return prop; } @Override public String toString() { return "ConnectionDescription [url=" + url + ", user=" + user + ", password=" + password + ", driverJarPaths=" + driverJarPaths + ", driverClassName=" + driverClassName + "]"; } }
修改后的getDriver()方法
private Driver getDriver(ConnectionDescription desc) throws ClassNotFoundException, MalformedURLException, InstantiationException, IllegalAccessException { // 用所有Jar路径拼接生成唯一标识,避免重复加载 String jarPathsKey = String.join(";", desc.getDriverJarPaths()); DriverId driverId = new DriverId(jarPathsKey, desc.getDriverClassName()); Driver driver = this.DRIVERS.get(driverId); if (driver == null) { ClassLoader parent = this.getClass().getClassLoader(); // 将多个Jar路径转换为URL数组供类加载器使用 URL[] jarUrls = desc.getDriverJarPaths().stream() .map(path -> { try { return new URL("file:" + path); } catch (MalformedURLException e) { throw new RuntimeException(e); } }) .toArray(URL[]::new); ClassLoader classLoader = URLClassLoader.newInstance(jarUrls, parent); @SuppressWarnings("unchecked") Class<Driver> driverClass = (Class<Driver>) classLoader.loadClass(desc.getDriverClassName()); driver = driverClass.newInstance(); this.DRIVERS.put(driverId, driver); } return driver; }
关键说明
- URLClassLoader支持传入多个Jar包的URL数组,加载Oracle驱动时会同时读取orai18n.jar中的字符集支持类,解决编码不兼容问题。
- 需保证orai18n.jar与ojdbc11.jar版本匹配,建议使用同一Oracle JDBC驱动包中的配套文件。
- DriverId的标识逻辑需覆盖多Jar组合场景,确保不同Jar组合不会被重复加载或错误复用。
内容的提问来源于stack exchange,提问作者user13746660
相关产品推荐
相关产品推荐

