在Clojure中捕获CQL删除列语句的特定异常问题排查
解决Cassandra DROP COLUMN时无法捕获InvalidQueryException的问题
问题核心是Alia库会将Datastax驱动抛出的原始异常包装成自身的异常类型,所以你直接捕获com.datastax.driver.core.exceptions.InvalidQueryException会失效——实际抛出的是Alia封装后的异常,原始异常被作为cause嵌套在里面。
解决步骤
先确认异常的实际类型:
在通用Exception分支里,打印异常的完整信息和嵌套的根异常:(catch Exception e (prn "当前异常类:" (class e)) (prn "根异常:" (.getCause e)) (prn "异常信息:" (.getMessage e)))你会发现实际抛出的是
qbits.alia.error.ExecutionException这类Alia自定义异常,原始的InvalidQueryException是它的根异常。修改异常捕获逻辑,以下是两种可行实现:
方案一:直接捕获Alia执行异常并检查根异常
(ns my-namespace (:require [qbits.alia :as alia] [qbits.hayt :as hayt]) (:import [com.datastax.driver.core.exceptions InvalidQueryException] [qbits.alia.error ExecutionException])) (defn drop-column-safe [session] (try (alia/execute session (hayt/alter-table :my_table (hayt/drop-column :my_col))) (catch ExecutionException ee (if (instance? InvalidQueryException (.getCause ee)) (prn "指定列不存在,无需删除") (prn "执行出错:" (.getMessage ee)))) (catch Exception e (prn "其他未知错误:" (.getMessage e)))))
方案二:在通用分支中递归判断根异常类型
(ns my-namespace (:require [qbits.alia :as alia] [qbits.hayt :as hayt]) (:import [com.datastax.driver.core.exceptions InvalidQueryException])) (defn drop-column-safe [session] (try (alia/execute session (hayt/alter-table :my_table (hayt/drop-column :my_col))) (catch Exception e (let [root-cause (loop [cause e] (if (.getCause cause) (recur (.getCause cause)) cause))] (if (instance? InvalidQueryException root-cause) (prn "指定列不存在,无需删除") (prn "错误信息:" (.getMessage e)))))))
额外优化方案:主动检查列是否存在
你也可以通过查询Cassandra系统表system_schema.columns预先判断列是否存在,再执行DROP操作,这种方式更主动:
(defn column-exists? [session keyspace table column] (let [result (alia/execute session (hayt/select :system_schema.columns (hayt/where :keyspace_name keyspace :table_name table :column_name column)))] (not-empty result))) (defn drop-column-if-exists [session] (when (column-exists? session "你的键空间名称" "my_table" "my_col") (alia/execute session (hayt/alter-table :my_table (hayt/drop-column :my_col)))))
内容的提问来源于stack exchange,提问作者BrianN
相关产品推荐
相关产品推荐

