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

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

ただいまの
回答率

90.34%

  • Java

    16766questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

DBのレコードを配列に格納したら一つのインデックスに複数行レコードが纏めて格納されてしまう

解決済

回答 2

投稿

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

pokemn

score 14

前提・実現したいこと

いつもお世話になっております。
現在、Javaで開発を行っているのですが、下記問題が発生しており困っております。
Dbaccess.javaクラスで1レコードを配列の0番目に2レコードを配列の1番目に格納...という風に動作させたいのですが、
現在では、2レコード目を格納しようとすると1番目に格納されるのですが、0番目のレコードにも追加されてしまいます。
この場合、どうしたら0番目に追加されずに1番目だけに値が入るようになりますでしょうか?
対象行:while(rset.next()) ~ userInfDto.setUserInformationList(list);
■下記、実際の配列の値になります。
※レコードが追加される度にすべてのインデックスに追加されてしまいます。
1レコード(最初):1, aaa ~
2レコード(最初):2, bbb ~
3レコード(最初):3, ccc ~
[[1, aaa, 2018-01-10, 2019-02-20, 1, null, 2, bbb, 2019-10-10, 2019-10-20, 2, null, 3, ccc, 2019-08-10, 2019-09-20, 3, null], 
[1, aaa, 2018-01-10, 2019-02-20, 1, null, 2, bbb, 2019-10-10, 2019-10-20, 2, null, 3, ccc, 2019-08-10, 2019-09-20, 3, null], 
[1, aaa, 2018-01-10, 2019-02-20, 1, null, 2, bbb, 2019-10-10, 2019-10-20, 2, null, 3, ccc, 2019-08-10, 2019-09-20, 3, null]]

どなたかご教授お願い致します。

■■な機能を実装中に以下のエラーメッセージが発生しました。

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

エラーメッセージ

該当のソースコード

public class Dbaccess extends Userinformationdto{

    DataSource ds;

    public Dbaccess() throws ServletException {
        try {
            InitialContext ic = new InitialContext();
            ds = (DataSource)ic.lookup("java:/comp/env/jdbc/SQLServer");

        } catch(Exception e) {

        }
    }

    public Userinformationdto Confimation(String user, int psw , Userinformationdto userInfDto) {

        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;

        try {
            con = ds.getConnection();
            if (user != null && psw != 0) {

                StringBuffer sql = new StringBuffer();

                sql.append("select user_id, user_name, user_password from user_table where user_name='" + user +"'" + "and user_password=" + psw );

                // sql文実行準備
                pstmt = con.prepareStatement(new String(sql));

                // sql文実行
                pstmt.execute();

                // 実行結果を、ResultSetクラスに代入
                rset = pstmt.executeQuery();
                if(rset.next()) {
                    userInfDto.setUser(rset.getString("user_name"));
                    userInfDto.setPsw(rset.getInt("user_password"));
                    System.out.println(getUser());
                    System.out.println(getPsw());
                    //StringBuilderの初期化を行います。
                    sql.delete(0, sql.length());
                    sql.append("select task_number, task_title, task_start_date, task_end_date, task_status, task_description from user_table INNER JOIN user_task_table on user_task_table.user_id='" + rset.getString("user_id") + "'where user_name='" + user +"'" + "and user_password=" + psw);
                    System.out.println(sql);
                    // sql文実行準備
                    pstmt = con.prepareStatement(new String(sql));
                    // sql文実行
                    pstmt.execute();
                    //結果格納前に初期化を行います。
                    rset = null;
                    System.out.println(getUser());
                    System.out.println(getPsw());
                    // 実行結果を、ResultSetクラスに代入
                    rset = pstmt.executeQuery();
                    ArrayList arrayList = new ArrayList();
                    List<ArrayList> list = new ArrayList();
                    while (rset.next()) {
                        arrayList.add(rset.getInt("task_number"));
                        arrayList.add(rset.getString("task_title"));
                        arrayList.add(rset.getDate("task_start_date"));
                        arrayList.add(rset.getDate("task_end_date"));
                        arrayList.add(rset.getInt("task_status"));
                        arrayList.add(rset.getString("task_description"));
                        list.add(arrayList);
                    }
                    userInfDto.setUserInformationList(list);
                }
            } else {
                return userInfDto;
            }
        } catch (SQLException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } finally {
            try {
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
        }
        return userInfDto;
    }

}

試したこと

userInfDto.setUserInformationList(list);をwhile(rset.next())の中に入れて、userInfDto.setUserInformationList(list);に
値を格納後、毎回arraylistを初期化してみたりしたのですが、うまくいきませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

ループ内で値を設定しております arrayList が, ループの1回目, 2回目, …で全て同じものを指しております.
list.add(arrayList);
によって list に格納されるのは arrayList への参照ですので, list の全ての要素が同じ arrayList を指すことになっております.

ArrayList arrayList = new ArrayList();

をループの開始直後に実行し, ループ毎に別の ArrayList にして頂く必要がございます.


回答とは関係ありませんが, ご注意頂きたく追記いたします.

SQL の実行におきまして

sql.append("select user_id, user_name, user_password from user_table where user_name='" + user +"'" + "and user_password=" + psw );
pstmt = con.prepareStatement(new String(sql));


のように SQL を Java の文字列として生成するのは危険です.

sql.append("select user_id, user_name, user_password from user_table where user_name=? and user_password=?");
pstmt = con.prepareStatement(sql.toString());
pstmt.setString(1, user);
pstmt.setString(2, psw);


のように, パラメータ設定をご利用ください.
SQLインジェクション対策となります.

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/24 22:17

    そもそもStringBuffer使っている意味が全くないというね…

    キャンセル

  • 2019/02/26 21:33

    遅くなり申し訳ありません。
    無事解決しました。
    またお二人のご指摘されている箇所も合わせて修正致します。
    まだまだ勉強中の為、お見苦しいソースコードで申し訳ありませんでした。

    キャンセル

0

回答はすでに出ていますが、いろいろ突っ込みたくなったので…

try-with-resourcesを使おう(Java8以降)

煩わしいfinallyでのリソースクローズをする必要がなくなります。

// 変更前
Connection con = null;
try {
    con = ds.getConnection();
    ....
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    try {
        if (con != null) {
            con.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

// 変更後
try (Connection con = ds.getConnection()) {
    ....
} catch (SQLException e) {
    e.printStackTrace();
}

StringBufferの意味全くナシ

jinbeさんの回答のコメントにも書いたけど、StringBufferの意味が全くないです。
ループなんかで繰り返し文字列連結をするなら効果がありますが、この場面では全くその特性が生かされていません。
普通の文字列連結で済みます。
(まあそもそもjinbeさんの回答の通り、SQLインジェクション対策の面では悪手ですが)

// 変更前(もう1か所あるが同じ)
sql.append("select user_id, user_name, user_password from user_table where user_name='" + user +"'" + "and user_password=" + psw );
pstmt = con.prepareStatement(new String(sql));

// 変更後
String sql1 = "select user_id, user_name, user_password from user_table where user_name='" + user +"'" + "and user_password=" + psw;
pstmt = con.prepareStatement(sql1);

Listなどのジェネリクスのない形(raw type)を使わない

これはsetUserInformationListメソッドの仕様にもよる、または影響しますが、ジェネリクスを使わない形は避けましょう。

// 変更前
ArrayList arrayList = new ArrayList();
List<ArrayList> list = new ArrayList();

// 変更後(ついでに左辺の型やジェネリクスをArrayListからListに変更)
List<Object> arrayList = new ArrayList<>();
List<List<Object>> list = new ArrayList<>();


まあそもそもこの結果格納用クラスでも用意しろよとは思うのですが…

まだあるけどとりあえずこんなところ…

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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

  • Java

    16766questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • トップ
  • Javaに関する質問
  • DBのレコードを配列に格納したら一つのインデックスに複数行レコードが纏めて格納されてしまう