質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

【Java,MySQL】構造が分からないDBから全てのテーブル、レコードを取得したい

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 352

tetutetu

score 348

前提・実現したいこと

Localhost内に存在する自身のデータベースの中身を自由に閲覧、編集できる機能(単純に、EclipseのDBViewerのような機能)を作成したい
→中身の構造が分からない(自身はもちろん知っているが、プログラム側には分からない の意)DBから値を取得したい
想定している大まかな流れとしては以下
データベース名からテーブル名を取得、全てのテーブル名をjsp内で表示(formで選択したテーブル名をサーブレットに渡す)
→渡されたテーブル名からカラム名、列数を取得
→ResultSet.getString("カラム名")を列数分取得して回したい
(ここまでで詰まっているため以下は未定)

発生している問題・エラーメッセージ

getString()の引数に変数を入れるとエラーを返されるため、列数分だけ回すことがそもそもできない

(今後発生するであろう問題として)
仮に列数分回すことができたとして、取得したレコードをまとまりごとにBean及びListに格納する方法が分からない

追記:
テーブル名、カラム名(+列数)の取得自体は済ませており、コード中のtable_nameには選択されたテーブル名が既に入っております。
また、記述外部分でカラム名をListとして持っておりますので、カラム名と列数は取得可能です。
res.getString()を列数回(参照するテーブルによって変わる変数)回す、取得した値をBeanに格納(.setXXXXメソッド)を効率的に扱う方法がお聞きしたいです。

該当のソースコード

//PreparedStatementにテーブル名を渡し、そのテーブルの全データを取得
String sql ="select * from ?";

        try (Connection con = ConnectionManager.getConnection();
                PreparedStatement pstmt = con.prepareStatement(sql);) {

            pstmt.setString(1, table_name);
            ResultSet res = pstmt.executeQuery();

            while(res.next()) {
//暫定的にboxに中身を受けとりたい getString()を列数ぶん回したい(while文なので回るが、変数が入らないため同じ値を取得し続けてしまう)
                String box = res.getString("ここに何を入れれば良いのでしょう");
//以下、略

試したこと

getString()の引数に変数を入れた(エラー)
単純にgetString(数字)を1~100まで(自身の作成したDBで想定しうる列数を大きく超えた数)書いた
→SQLException(数字が列数を超えた時点でカラムが存在しないエラー
試しにSQLExceptionをcatchした→当然何も出力されない

Beanに現在DBに存在する全てのカラムについてのgetter,setterを作成 if文で分岐しようとした
→ある程度までの動作はするがとんでもなく冗長、かつDBにカラムが追加されたらそれに対応できない

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+1

ResultSetMetaData (Java Platform SE 8 ) が使えると思います。

今、手元にサンプルソースを作って提示できる環境がないので書き方は他の方が書いたブログを参照してください。
Java ResultSetMetaDataクラスを使ってカラム名を取得する

記載があるコードから一部を抜き出すと、

ResultSetMetaData meta = rs.getMetaData();
System.out.println("カラム数:" + meta.getColumnCount());
System.out.println("1つ目のカラム名:" + meta.getColumnName(1));

この辺りを使って対応できるのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 16:12

    回答ありがとうございます。
    今回、カラム名、カラム数を取得する際
    配列にカラム名を格納して配列の要素数をカウントしていたのですが
    このような方法もあったのですね。
    カラム数分回してBeanに格納する、という設計自体が本来の機能から逸脱した動作であったため、当初想定していた機能は作成できませんでしたが、今後の参考にさせていただきます。

    キャンセル

0

取得した値をBeanに格納

データの形が一致しないテーブルを同じBeanに投入するという構造そのものに無理があるのではないかと考えます。

HashMapなどに入れておくしかないのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 16:06

    回答ありがとうございます。
    確かに、少し考えてみればBeanの本来の動作を逸脱した動きをさせようとしていましたね。
    趣味としての開発で納期なども存在しないので、改めて考えてみようと思います。

    キャンセル

0

端的に言えば、やろうとしていることはセキュリティのスキをついて
インジェクションをしかけるのとたいして違いがありません。
(構造がわからないけど無理やりSQL文を閉じて、別のSQLを発行する的な・・・)
基本的には構造をしらないようなクライアントにテーブルアクセスを許してはいけません。

スーパーユーザー的なユーザーであればダンプすれば、テーブルのすべてを無条件で
得ることができるでしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 16:08

    回答ありがとうございます。
    構造を知らないクライアントがアクセスするのではなく
    一つのDAOのメソッドで、どのテーブルにもアクセスできる
    (そのために列数が必要)機能を持たせられればと思い、質問させていただいた次第です。

    キャンセル

-2

SHOW TABLES FROM データベース名
で指定のデータベースのテーブル一覧取得
SHOW COLUMNS FROM テーブル名
で指定のテーブルのカラム情報取得

あとはよしなに。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 11:08

    回答ありがとうございます。
    私の文章力が足りず、申し訳ありませんが
    テーブル名や、テーブルに対応したカラム名(及び列数)は記述外の部分ですでに取得済みです。
    Javaの方で列数分(テーブルにより変動)のみ処理を回し、効率的に値を格納する方法をお聞きしたい次第です。

    キャンセル

  • 2019/06/21 11:16

    Listをforで回せばいいんじゃないですか?
    正直なところ「別で持っている」よりも
    テーブル一覧取得してループ

    テーブルカラム取得 

    テーブルデータ取得
    テーブルカラムループ

    という流れにすべきかと思います。

    Beanについては変動してカラムも削除されたり追加されたり定義が変わったりするので
    List<String,Object> で全部1個の配列で持っておくしかないかと。

    キャンセル

-2

SQL標準ではDBの情報をまとめたものとして、information_schemaが定められています。
それを利用するのが良いかと思います。
MySQL でテーブルやカラムの情報を確認する方法まとめ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 11:08

    回答ありがとうございます。
    私の文章力が足りず、申し訳ありませんが
    テーブル名や、テーブルに対応したカラム名(及び列数)は記述外の部分ですでに取得済みです。
    Javaの方で列数分(テーブルにより変動)のみ処理を回し、効率的に値を格納する方法をお聞きしたい次第です。

    キャンセル

  • 2019/06/21 11:15

    カラム毎の処理を行いたいなら、敢えて変数に列数分の情報を配列で格納するより、information_schemaを元にfetchすれば良いのでは?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る