HiveJDBC与其他JDBC一起使用时出现java.lang.IllegalArgumentException: Bad URL format

本文介绍了一个关于在Java程序中同时使用Hive和MySQL数据库时遇到的问题及解决方案。当通过JDBC访问MySQL时,由于Hive JDBC驱动的不当实现导致出现BadURLformat异常。文中提供了两种解决方法:一是升级到新版本的Hive JDBC驱动;二是修改获取连接的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

程序中需要使用JDBC的方式同时访问Hive和MySQL,发现在获取MySQL连接的时候(DriverManager.getConnection方法)出现Hive的类中的Bad URL format异常。

代码如下:

 public Connection getMySqlConn() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(ConstantUtil.mysqlUrl, ConstantUtil.mysqlUsername, ConstantUtil.mysqlPassword);
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage(), e);
        } catch (SQLException e) {
            logger.error(e.getMessage(), e);
        }
        return conn;
    }

异常如下:

java.lang.IllegalArgumentException: Bad URL format
        at org.apache.hive.jdbc.Utils.parseURL(Utils.java:185)
        at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:84)
        at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:104)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:247)
        at com.xxx.util.MySqlUtil.getMySqlConn(MySqlUtil.java:33)
        at com.xxx.interceptor.TransformInterceptor.refreshApp(TransformInterceptor.java:151)
        at com.xxx.interceptor.TransformInterceptor.initialize(TransformInterceptor.java:42)
        at org.apache.flume.interceptor.InterceptorChain.initialize(InterceptorChain.java:74)
        at org.apache.flume.channel.ChannelProcessor.initialize(ChannelProcessor.java:68)
        at org.apache.flume.source.PollableSourceRunner.start(PollableSourceRunner.java:70)
        at org.apache.flume.lifecycle.LifecycleSupervisor$MonitorRunnable.run(LifecycleSupervisor.java:249)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

原因分析:

DriverManager.getConnection方法会使用url去尝试访问每个注册的JDBCDriver的connect方法,而JDBC的规范中要求该方法要判断url是否能够处理,不能处理要返回null。
然而,hive-jdbc在0.11.0版本中(具体受影响的版本范围未分析),调用其connect方法时,在url前缀非hive的情况下,是直接抛出IllegalArgumentException,而这个异常DriverManager并不会捕获,导致程序直接报错,不再尝试正确的MySQL的Driver。

解决办法:

(1)新版本的HiveJdbcDriver已修改这个问题。即先判断url前缀是否可以处理(处理不了返回null),并且将parseURL的异常修改为SQLException的子类(DriverManager会捕获)。
(2)将调用的代码改为,先获取你需要的Driver,再调用具体Driver的connect方法,这样DriverManager就不会去尝试调用每个Driver的connect方法了。代码如下:

public Connection getMySqlConn() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Driver driver = DriverManager.getDriver(ConstantUtil.mysqlUrl);
            java.util.Properties info = new java.util.Properties();
            info.put("user", ConstantUtil.mysqlUsername);
            info.put("password", ConstantUtil.mysqlPassword);
            conn = driver.connect(ConstantUtil.mysqlUrl, info);
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage(), e);
        } catch (SQLException e) {
            logger.error(e.getMessage(), e);
        }
        return conn;
    }
`java.lang.IllegalArgumentException: MALFORMED` 这种异常通常表示传递给方法的参数格式错误,不符合预期的结构。在Java中,如果两个异常的消息内容非常相似,比如都是指数据格式错误,那么在处理这类异常,可以采取以下策略来兼容: 1. **捕获通用异常**:创建一个能捕获 `IllegalArgumentException` 的宽泛捕获异常块,然后在 `catch` 体内检查具体异常消息。如果消息包含 "MALFORMED" 字符串,就可以统一处理。 ```java try { // 调用可能会抛出异常的方法 } catch (IllegalArgumentException e) { if (e.getMessage().contains("MALFORMED")) { handleMalformedData(e); } else { // 处理其他类型的IllegalArgumentException } } ``` 2. **自定义异常信息**:如果可能的话,在调用方修改代码,提供更明确的异常信息,如 `IllegalArgumentException("Invalid format")` 或 `IllegalArgumentException("Malformed data detected at index X")`,这样可以避免直接匹配字符串。 3. **使用枚举**:如果`MALFORMED` 是一组特定的异常情况之一,可以将它们定义为枚举,然后根据枚举值进行判断和处理。 ```java public enum MalformationReason { DATA_FORMAT, INDEX_OUT_OF_BOUNDS, // 其他原因... } try { // ... } catch (IllegalArgumentException e) { MalformationReason reason = MalformationReason.valueOf(e.getMessage()); switch (reason) { case DATA_FORMAT: handleMalformedData(e); break; // 其他分支... } } ``` 无论哪种方法,都需要确保你的代码能够清晰地表达出异常的原因,以便于调试和维护。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值