web-dev-qa-db-fra.com

JDBC ResultSet obtient des colonnes avec un alias de table

Imaginez que j'ai une requête comme 

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

Peut-être que les deux tables ont le même nom de colonne. Je pensais donc que ce serait bien d’accéder aux données via

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

Mais cela se retourne contre moi et je ne reçois rien. J'ai lu l'API, mais ils ne parlent pas vraiment de cette affaire. Une telle fonctionnalité dépend-elle du fournisseur?

43
Franz Kafka

JDBC nommera simplement les colonnes en fonction de ce qui est spécifié dans la requête - il ne connaît pas les noms de table, etc.

Vous avez deux options:

Option 1: Nommez les colonnes différemment dans la requête, c'est-à-dire

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

puis dans votre code Java, reportez-vous aux alias de colonnes:

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


Option 2: Reportez-vous à la colonne position de votre appel à l'API JDBC:

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

Notez que l’API JDBC utilise les index one-based - c’est-à-dire qu’ils comptent à partir de 1 (pas à partir de 0 comme les index Java), utilisez donc 1 pour la première colonne, 2 pour la deuxième colonne, etc.


Je recommanderais l'option 1, car il est plus sûr de se référer aux colonnes nommées: quelqu'un pourrait changer l'ordre des colonnes dans la requête et cela casserait votre code en silence (vous accéderiez à la mauvaise colonne sans le savoir), mais s'ils changent les noms des colonnes, vous obtiendrez au moins une exception "aucune colonne de ce type" au moment de l'exécution. 

45
Bohemian

ResultSetMetadata.getColumnLabel () est ce dont vous avez besoin

(edit) exemple, comme indiqué par bharal dans un commentaire

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

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

Utilisez des alias de colonne comme:

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

Et spécifiez toutes les colonnes que vous récupérez (est une bonne pratique).

8

Si vous utilisez MySQL, ajoutez simplement 

&useOldAliasMetadataBehavior=true

à votre connectionString. 

Ensuite, vous pouvez utiliser ce petit assistant:

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

}
5

Ok, il semble qu’il n’existe aucune méthode comme resultSet.getString("a.columnName"); Vous devez aliaser vos colonnes au niveau SQL, Mais dans la mesure où il existe une méthode getTableName(iCol), j’espère que les gars de Java.sql.ResultSet ajouteront une telle fonctionnalité.

1
Mostafa

Vous pouvez utiliser un alias au niveau SQL . Vous récupérez ensuite les données par index. (Mais cette approche fera de la maintenance un véritable cauchemar)

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

String value = rs.getString(1);
0
Ammar

Une idée que j’ai eue est d’utiliser la getTableName(iCol) pour saisir les noms de table des colonnes nommées en double, puis encapsuler un hachage de vos propres clés (avec le préfixe du nom de table) qui vous dirigerait vers le bon index de colonne et référencer votre colonne -les valeurs de cette façon. Cela nécessiterait une boucle initiale dans les métadonnées au début pour la mise en place. Le seul problème que je vois avec ceci est que vous aliasez également les noms de table. Je n'ai pas encore trouvé le moyen d'obtenir ces alias de noms de tables à partir de jdbc sans les gérer vous-même lorsque vous construisez l'instruction sql. Cette solution dépendrait de ce que le gain syntaxique serait pour vous.

0
inyourcorner