JDBC ResultSet get columns with table alias

JavaSqlOracleJdbcResultset

Java Problem Overview


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. Is such a feature vendor dependent?

Java Solutions


Solution 1 - Java

JDBC will simply name the columns by what is specified in the query - it doesn't know about table names etc.

You have two options:

Option 1: Name the columns differently in the query, ie

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:

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


Option 2: Refer to the column position in your call to the 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


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.

Solution 2 - Java

ResultSetMetadata.getColumnLabel() is what you need

(edit) sample example, as stated by bharal in comment

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

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

Solution 3 - Java

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).

Solution 4 - Java

If you are using MySQL just add

&useOldAliasMetadataBehavior=true

to your 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);
    }
    
}

Solution 5 - Java

Ok, it seems there's no method like 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.

Solution 6 - Java

You can use alias on SQL level. 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);

Solution 7 - Java

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. 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. This solution would depend on what the syntactical pay-off would be to you.

Solution 8 - Java

Change your sql into

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");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFranz KafkaView Question on Stackoverflow
Solution 1 - JavaBohemianView Answer on Stackoverflow
Solution 2 - JavaMateenView Answer on Stackoverflow
Solution 3 - JavaDavid Oliván UbietoView Answer on Stackoverflow
Solution 4 - JavaHalko Karr-SajtarevicView Answer on Stackoverflow
Solution 5 - JavaMostafaView Answer on Stackoverflow
Solution 6 - JavaAmmarView Answer on Stackoverflow
Solution 7 - JavainyourcornerView Answer on Stackoverflow
Solution 8 - Javauser2979180View Answer on Stackoverflow