1

安らかな API を作成するには Java を処理する必要があり、MySQL でそれを使用して DB にクエリを実行しています。

私は Java にまったく慣れていないため、これは非常に基本的な質問かもしれませんが、この問題が存在しない PHP フレームワークに慣れていて、Java でそれを行う方法を知りたいと思っていました。

外部キーでそれらを結合する 3 つのテーブルをクエリしていますが、それらのテーブルのうち 2 つに同じ列名がある場合、そのうちの 1 つだけが返されることがわかりました。fromステートメントで宣言された最新のテーブルからのもの。彼らはオーバーライドされるようです。

たとえば、テーブルtype_applicationとテーブルのtype_leaves両方に列がある場合、次のクエリでは列nameのみが返されます。nametype_leaves

select * from leaves, type_applications, type_leaves 
    where leaves.type_leave = type_leaves.id and 
    leaves.type_application = type_applications.id;

asこれで、テーブル名の前に必要なすべての列名を指定し (それらが重複している場合) 、エイリアス名を作成するために使用することで、これを簡単に解決できることがわかりました。

select leaves.id, type_leaves.name as leaves_name, type_applications.name as application_name
    from leaves, type_applications, type_leaves 
    where leaves.type_leave = type_leaves.id and 
    leaves.type_application = type_applications.id;

しかし、これは私にとって最善の解決策とは思えません。すべてのフィールドを取得するために、 を使用し続け*たいと思います (これは、私が常に望んでいることです)。

これはまた、時間の経過とともにテーブルの列を追加または削除し続ける場合に備えて、クエリを小さくし、読みやすく、維持しやすくするのにも役立ちます。

これに対する解決策はありますか?Javaでそれを処理する方法は何ですか?

4

5 に答える 5

4

私もJavaは初めてなので、あなたのことを聞いています;)。でも、答えを出すために最善を尽くす前に、よろしければ一言言いたいと思います。あなたの質問は、Java とデータベース/SQL に関連しています。DBテーブルとクエリから得られるものについていくつか説明するSQLを提供しました。しかし、あなたの主な問題は Java にあり、Java コードを提供しなかったため、あなたが何を達成しようとしているのか、どこで問題が発生しているのかをよりよく理解できます。そうは言っても、次のことがあなたに何ができるかについてのアイデアを与えることを願っています:

まず、ResultSetクエリの には両方のname列が含まれています。それらは上書きされません。次に例を示します。

String sql = "select * from leaves, type_applications, type_leaves " +
                "where leaves.type_leave = type_leaves.id and " +
                "leaves.type_application = type_applications.id";

ResultSet rs = stmt.executeQuery(sql);
DBTablePrinter.printResultSet(rs);

これにより、次のように出力されます。

Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID |        NAME        | ID |     NAME     |
+----+------------------------+----+--------------------+----+--------------+
|  1 | green                  |  1 | application type 1 |  1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+

ご覧のとおり、両方のname列があります。(私が書いた DBTablePrinter ユーティリティ クラスを使用しました。興味がある場合は、ここで見つけることができます)。Strawberry がコメントで行ったように、明示的な結合構文の使用を検討することもお勧めします。

私は他の DB (H2) を使用しているため、これが MySQL で機能するかどうかはわかりませんが、試すことができます (私にとっては機能しました)。

// After executing the query
rs.next();
System.out.println(rs.getString("TYPE_LEAVES.NAME"));
System.out.println(rs.getString("TYPE_APPLICATIONS.NAME"));

// Prints:
// leave type 1
// application type 1

これが機能しない場合、または列名にプレフィックスを付けてこれらの新しい名前でアクセスする必要がある場合、私が考えることができるのは次のようなものだけです:

ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();

// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);

// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
    if (rsmd.getColumnLabel(i).equals("NAME")) {
        if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
            columns.put("L_NAME", new ArrayList<>());
        } else {
            columns.put("APP_NAME", new ArrayList<>());
        }
    } else {
        columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
    }
}

// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
    for (int i = 1; i <= columnCount; i++) {
        String columnName = rsmd.getColumnLabel(i);
        String tableName = rsmd.getTableName(i);
        if (columnName.equals("NAME")) {
            if (tableName.equals("TYPE_LEAVES")) {
                columns.get("L_NAME").add(rs.getString(i));
            } else {
                columns.get("APP_NAME").add(rs.getString(i));
            }
        } else {
            columns.get(columnName).add(rs.getString(i))
        }
    }
}

// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));

// Prints:
// leave type 1
// application type 1
于 2014-11-04T23:50:31.337 に答える
1

以下のように、不足している列を明示的に取得してみてください。

select *,type_applications.name as type_applications_name
  from leaves, type_applications, type_leaves 
    where leaves.type_leave = type_leaves.id and 
    leaves.type_application = type_applications.id;
  1. とにかく、クロス結合の使用はお勧めできません。
  2. select * の使用は推奨されません。

ただし、とにかくselect *が必要な場合は、テーブルを使用して結果をラップしてみてください。

select * from (
select leaves.*, type_applications.*, type_leaves.* ,type_applications.name as type_applications_name
  from leaves, type_applications, type_leaves 
    where leaves.type_leave = type_leaves.id and 
    leaves.type_application = type_applications.id;
)

PS: コードをテストしていないため、入力ミスがある可能性があるため、アイデアだけを取得してください。

于 2014-11-05T08:45:07.863 に答える
0

このシナリオでは、列の 1 つが名前変更されている可能性があります。

この問題を回避するには、executeQuery (ResultSet.getMetaData メソッド) によって返される結果セットから列のリストをクエリできます。これはhttp://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.htmlのインスタンスを返します

  1. getColumnCount() は結果の列数を返します
  2. getColumnLabel(int column) はその列の名前を返します

2 つの列に同じ名前 "name" がある場合、それら 2 つの列のラベルが異なる場合があります。

于 2014-10-29T11:27:59.587 に答える