JDBC中的getColumnLabel和getColumnName

本文解析了JDBC中getColumnLabel与getColumnName方法的差异,解释了它们在Oracle与MySQL驱动中的具体实现,强调在多数据库适配时应使用getColumnLabel以避免错误。

最近开发的一个提取数据的服务在适配mysql时出现了问题,用ResultSetMetaData.getColumnName获取的列名并非sql语句中设定的别名,导致结果集输出错误,代码如下:

for (int i = 1; i <= metaData.getColumnCount(); i++) {
    map.put(metaData.getColumnName(i), resultSet.getObject(i));
}

其中错误的将getColumnName方法理解为getColumnLabel,所以在这里对两个方法做下说明。

首先看下JDBC中对这两个方法的定义

    /**
     * Gets the designated column's suggested title for use in printouts and
     * displays. The suggested title is usually specified by the SQL <code>AS</code>
     * clause.  If a SQL <code>AS</code> is not specified, the value returned from
     * <code>getColumnLabel</code> will be the same as the value returned by the
     * <code>getColumnName</code> method.
     *
     * @param column the first column is 1, the second is 2, ...
     * @return the suggested column title
     * @exception SQLException if a database access error occurs
     */
    String getColumnLabel(int column) throws SQLException;

    /**
     * Get the designated column's name.
     *
     * @param column the first column is 1, the second is 2, ...
     * @return column name
     * @exception SQLException if a database access error occurs
     */
    String getColumnName(int column) throws SQLException;

注释说明getColumnLabel返回的是列标题getColumnName返回的是列名,列标题和列名看起来是一个东西,其实并非这么简单,列标题是指select语句中的列别名,也就是查询结果集中显示出来的列,而列名指的是数据库表中的列名,以下边的sql为例

select c1 as label from t

getColumnLabel应该返回label,getColumnName应该返回c1。

当然,这只是JDBC对这两个方法的定义,在各个数据库驱动中对该方法的实现还有所不同。先来看下oracle的代码。

    public String getColumnLabel(int var1) throws SQLException {
        return this.getColumnName(var1);
    }

    public String getColumnName(int var1) throws SQLException {
        int var2 = this.getValidColumnIndex(var1);
        return this.statement.getDescriptionWithNames()[var2].columnName;
    }

没错,getColumnLabel直接调用了getColumnName,也就是说在oracle中这两个其实是同一个方法,返回的是sql中的列别名。再来看下mysql的代码。

    public String getColumnLabel(int column) throws SQLException {
        return this.useOldAliasBehavior ? this.getColumnName(column) : this.getField(column).getColumnLabel();
    }

    public String getColumnName(int column) throws SQLException {
        if (this.useOldAliasBehavior) {
            return this.getField(column).getName();
        } else {
            String name = this.getField(column).getNameNoAliases();
            return name != null && name.length() == 0 ? this.getField(column).getName() : name;
        }
    }

可以看到,mysql参照JDBC的定义,getColumnLabel返回了列别名,getColumnName返回了列名,同时mysql提供了一个useOldAliasBehavior参数,当其为true时,就会完全使用列别名当作列名,这个参数可以使用useOldAliasMetadataBehavior=true配置到url中,这时方法含义又和oracle中的相同了。

最后建议在代码中使用getColumnLabel,因为其在各个驱动版本中的含义是相同的,可以避免多数据库适配时出现的错误。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值