简体   繁体   English

JDBC ResultSet 获取带有表别名的列

[英]JDBC ResultSet get columns with table alias

Imagine I have a query like想象一下我有一个类似的查询

SELECT * from table1 a, table2 b where (WHATEVER)

Maybe both tables have the same column name.也许两个表都有相同的列名。 So I though it would be nice to access the data via所以我认为通过访问数据会很好

resultSet.getString("a.columnName");
resultSet.getString("b.columnName");

But this backfires on me and I get nothing.但这对我适得其反,我一无所获。 I read the API, but they don't really talk about this case.我阅读了 API,但他们并没有真正谈论这个案例。 Is such a feature vendor dependent?此类功能是否依赖于供应商?

JDBC will simply name the columns by what is specified in the query - it doesn't know about table names etc. JDBC 将简单地根据查询中指定的内容命名列 - 它不知道表名等。

You have two options:您有两个选择:

Option 1: Name the columns differently in the query, ie选项 1:在查询中以不同的方式命名列,即

SELECT
    a.columnName as columnNameA,
    b.columnName as columnNameB,
    ...
from table1 a, table2 b where (WHATEVER)

then in your java code refer to the column aliases:然后在您的 java 代码中引用列别名:

resultSet.getString("columnNameA");
resultSet.getString("columnNameB");


Option 2: Refer to the column position in your call to the JDBC API:选项 2:参考您对 JDBC API 的调用中的列位置

resultSet.getString(1);
resultSet.getString(2);

Note that the JDBC API uses one-based indexes - ie they count from 1 (not from 0 like java indexes), so use 1 for the first column, 2 for the second column, etc请注意,JDBC API 使用基于一个的索引 - 即它们从1计数(而不是像 java 索引那样从0 ),因此对第一列使用1 ,对第二列使用2 ,等等


I would recommend option 1, because it's safer to refer to named columns: Someone may change the order of the columns in the query and it would silently break your code (you would be accessing the wrong column but would not know), but if they change the columns names, you'll at least get a "no such column" exception at runtime.我会推荐选项 1,因为引用命名列更安全:有人可能会更改查询中列的顺序,它会默默地破坏您的代码(您将访问错误的列但不知道),但如果他们更改列名称,您至少会在运行时收到“无此类列”异常。

ResultSetMetadata.getColumnLabel() is what you need ResultSetMetadata.getColumnLabel() 就是你所需要的

(edit) sample example, as stated by bharal in comment (编辑)示例示例,如 bharal 在评论中所述

SELECT * from table1 a, table2 b where (WHATEVER)

ResultSetMetaData rsmd = rset.getMetaData();
rsmd.getColumnLabel(1);

Use column aliases like:使用列别名,如:

SELECT A.ID 'A_ID', B.ID 'B_ID' FROM TABLE1 AS A, TABLE2 AS B...

And specify all the columns you are retrieving (is a good practice).并指定您要检索的所有列(这是一个很好的做法)。

If you are using MySQL just add如果您使用的是 MySQL,只需添加

&useOldAliasMetadataBehavior=true

to your connectionString.到您的 connectionString。

Afterwards you can use this little Helper:之后你可以使用这个小助手:

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class ResultSetHelper {

    private final Map<String, Integer> columnMap;

    public ResultSetHelper(ResultSet rs) throws SQLException {
        this.columnMap = new HashMap<>();
        ResultSetMetaData md = rs.getMetaData();
        int columnCount = md.getColumnCount();
        for (int index = 1; index <= columnCount; index++) {
            String columnName = md.getColumnLabel(index);
            if (!columnMap.containsKey(columnName)) {
                columnMap.put(columnName, index);
            }

            String tableAlias = md.getTableName(index);
            if (tableAlias != null && !tableAlias.trim().isEmpty()) {
                columnMap.put(tableAlias + "." + columnName, index);
            }
        }
    }

    public Integer getColumnIndex(String columnName) {
        return columnMap.get(columnName);
    }

    public Integer getColumnIndex(String tableAlias, String columnName) {
        return columnMap.get(tableAlias + "." + columnName);
    }

}

Ok, it seems there's no method like resultSet.getString("a.columnName");好吧,似乎没有像resultSet.getString("a.columnName");这样的方法resultSet.getString("a.columnName"); and you have to alias your columns at sql level, but inasmuch as there's a getTableName(iCol) method I hope guys at java.sql.ResultSet add such a feature.并且您必须在 sql 级别为您的列添加别名,但是由于有一个getTableName(iCol)方法,我希望java.sql.ResultSet添加这样一个功能。

Change your sql into把你的sql改成

SELECT a.*, b.* from table1 a, table2 b where (WHATEVER)

than you can read from resulset by table alias比您可以通过表别名从结果集读取

resultSet.getString("a.columnName");
resultSet.getString("b.columnName");

You can use alias on SQL level.您可以在 SQL 级别使用别名。 Then you retrieve data by indexes.然后按索引检索数据。 (But this approach will make maintenance a real nightmare) (但这种方法会使维护成为真正的噩梦)

SELECT a.column, b.column FROM table1 a, table2 b

String value = rs.getString(1);

One idea I had is to use the getTableName(iCol) to grab the table names for the duplicately-named columns, then wrap a hash of your own keys (with the table name prefix) that would point you to the correct column index, and reference your column-values that way.我的一个想法是使用getTableName(iCol)来获取重复命名列的表名,然后包装您自己的键的散列(带有表名前缀),它将指向正确的列索引,并且以这种方式引用您的列值。 This would require an initial loop through the meta data at the beginning to set up.这将需要在开始时通过元数据进行初始循环以进行设置。 The only issue I see with this is that you are aliasing the table names as well.我看到的唯一问题是您还为表名设置了别名。 I've yet to find a way of getting those table name aliases from jdbc without managing it yourself when you build the sql statement.我还没有找到一种从 jdbc 获取这些表名别名的方法,而无需在构建 sql 语句时自己管理它。 This solution would depend on what the syntactical pay-off would be to you.这个解决方案将取决于你的语法回报。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM