web-dev-qa-db-ja.com

JDBC ResultSetは、テーブルエイリアスを持つ列を取得します

次のようなクエリがあると想像してください

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

両方のテーブルの列名が同じである場合があります。だから私はそれを介してデータにアクセスするのはいいだろうが

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

しかし、これは私に裏目に出て、何も得られません。私はAPIを読みましたが、彼らは実際にこのケースについて話をしていません。そのような機能ベンダーは依存していますか?

46
Franz Kafka

JDBCは、クエリで指定された名前で列に名前を付けるだけです。テーブル名などはわかりません。

次の2つのオプションがあります。

オプション1:クエリで列に異なる名前を付ける

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

次に、Javaコードで列エイリアスを参照します。

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


オプション2: JDBC APIの呼び出しの列positionを参照してください。

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

JDBC APIはone-basedインデックスを使用することに注意してください-つまり、1からカウントします(0からではなくJavaインデックス)、最初の列に1、2番目の列に2などを使用します


名前付き列を参照する方が安全であるため、オプション1をお勧めします。誰かがクエリ内の列の順序を変更すると、コードが静かに壊れてしまいます(間違った列にアクセスすることになるが、 )、ただし、列名を変更すると、少なくとも実行時に「そのような列はありません」例外が発生します。

45
Bohemian

ResultSetMetadata.getColumnLabel()は必要なものです

(編集)bharalのコメントに記載されているサンプル例

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

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

次のような列エイリアスを使用します。

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

そして、取得するすべての列を指定します(良い方法です)。

MySQLを使用している場合は、追加するだけです

&useOldAliasMetadataBehavior=true

connectionStringに。

その後、この小さなヘルパーを使用できます。

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、resultSet.getString("a.columnName");のようなメソッドはないようで、SQLレベルで列にエイリアスを作成する必要がありますが、getTableName(iCol)メソッドがあるので、Java.sql.ResultSetそのような機能を追加します。

1
Mostafa

SQLレベルでエイリアスを使用できます。次に、インデックスによってデータを取得します。 (しかし、このアプローチはメンテナンスを本当に悪夢にします)

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

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

私が持っていた1つのアイデアは、getTableName(iCol)を使用して重複する名前の列のテーブル名を取得し、正しい列を指す独自のキーのハッシュを(テーブル名のプレフィックスで)ラップすることですインデックスを作成し、列値をそのように参照します。これには、設定の開始時にメタデータを最初にループする必要があります。これに関して私が見る唯一の問題は、テーブル名もエイリアスしているということです。 sqlステートメントを作成するときに自分で管理せずにjdbcからこれらのテーブル名エイリアスを取得する方法をまだ見つけていません。この解決策は、構文上の見返りがどのようになるかによって異なります。

0
inyourcorner