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

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

ただいまの
回答率

90.49%

  • Java

    16139questions

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

  • オブジェクト指向

    331questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

オブジェクト指向の考え方に関して

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 342

lianprivate

score 13

現在JavaでDB連携の勉強をしております。
その中で疑問に思ったのですが、現在3つのテーブルをそれぞれユーザーIDで管理し、それを結合して出力するという事を行う上で、Javaからそれぞれのテーブルのデータ更新や登録、消去を行おうとしています。

やりたい事は概ね出来上がってきたのですが、その中で更新、登録、消去をそれぞれクラスを作り、メインメソッドでそれぞれのクラスを呼び出し、その中でそれぞれの処理を実施しています。

まず1点は、この方法はJavaの考え方では正しい方法なのでしょうか?

そして2点目ですが、その各クラスの中でその3つのテーブルの操作を同じメソッドで行っていますが、メインメソッドからクラスを呼び出す際にそれぞれを識別する値を引数で渡し、それを元にif分で分岐させ、それぞれの処理を実施していますが、その方法ですとどうしてもコードが長くなってしまいます。
果たしてJavaではこのようなやり方で合っているのでしょうか?

下記にその呼び出されるクラスの中でも一番短いDB登録後のID検索のメソッドを添付致します。
例えばDB更新のクラスですとこの数倍の長さになります。
お手数ですがご見解を教えていただけますでしょうか。宜しくお願い致します。

public class Serch {
    public int SerchID() {
        int Uid = 0;
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rset = null;

        //接続文字列
        String url = "jdbc:postgresql://localhost:5432/sample";
        String user = "postgres";
        String password = "Password";

        try{
            Class.forName("org.postgresql.Driver");

            //PostgreSQLへ接続
            conn = DriverManager.getConnection(url, user, password);

            //自動コミットOFF
            conn.setAutoCommit(false);

            //SELECT文の実行
            String sql = "SELECT MAX(Uid) FROM m_user";
            stmt = conn.prepareStatement(sql);
            rset = stmt.executeQuery();

            //SELECT結果の受け取り
            while(rset.next()){
                Uid = Integer.parseInt(rset.getString(1));
            }
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (SQLException e){
            e.printStackTrace();
        }
        finally {
            try {
                if(rset != null)rset.close();
                if(stmt != null)stmt.close();
                if(conn != null)conn.close();
            }
            catch (SQLException e){
                e.printStackTrace();
            }

        }
        return Uid;
    }

    public void LatestDate(int Uid,int DB) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rset = null;

        //接続文字列
        String url = "jdbc:postgresql://localhost:5432/sample";
        String user = "postgres";
        String password = "Qoakzm12";

        try{
            Class.forName("org.postgresql.Driver");

            //PostgreSQLへ接続
            conn = DriverManager.getConnection(url, user, password);

            //自動コミットOFF
            conn.setAutoCommit(false);

            //SELECT文の実行
            if(DB == 1) {
                String sql = "SELECT * FROM m_user WHERE Uid = ?";
                stmt = conn.prepareStatement(sql);
                stmt.setLong(1,Uid);
                rset = stmt.executeQuery();

                //SELECT結果の受け取り
                while(rset.next()){
                    System.out.println("1件の登録が完了しました。");
                       System.out.println("名前:" + rset.getString(1));
                    System.out.println("年齢:" + rset.getString(2));
                    System.out.println("住所:" + rset.getString(3));
                    System.out.println("性別:" + rset.getString(4));
                    System.out.println("登録日:" + rset.getString(5));
                    System.out.println("ユーザーID:" + rset.getString(6));
                }
            }else if(DB == 2) {
                String sql = "SELECT * FROM privacy_tbl WHERE UserId = ?";
                stmt = conn.prepareStatement(sql);
                stmt.setLong(1,Uid);
                rset = stmt.executeQuery();

                //SELECT結果の受け取り
                while(rset.next()){
                    System.out.println("1件の登録が完了しました。");
                       System.out.println("ユーザーID:" + rset.getString(1));
                    System.out.println("EMAILアドレス:" + rset.getString(2));
                    System.out.println("電話番号:" + rset.getString(3));
                    System.out.println("郵便番号:" + rset.getString(4));
                    System.out.println("居住国:" + rset.getString(5));
                }
            }else if(DB == 3) {
                 String sql = "SELECT * FROM Otherinfo WHERE InfoId = ?";
                 stmt = conn.prepareStatement(sql);
                 stmt.setLong(1,Uid);
                 rset = stmt.executeQuery();

                 //SELECT結果の受け取り
                 while(rset.next()){
                     System.out.println("1件の登録が完了しました。");
                        System.out.println("ユーザーID:" + rset.getString(1));
                     System.out.println("趣味:" + rset.getString(2));
                     System.out.println("特技:" + rset.getString(3));
                     System.out.println("夢:" + rset.getString(4));
                 }
            }
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (SQLException e){
            e.printStackTrace();
        }
        finally {
            try {
                if(rset != null)rset.close();
                if(stmt != null)stmt.close();
                if(conn != null)conn.close();
            }
            catch (SQLException e){
                e.printStackTrace();
            }

        }
    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/12/21 11:13

    新規質問立つまでの間に回答作ってみてたのでそのまま投稿しました。
    ご参考まで。

    キャンセル

  • hayataka2049

    2018/12/21 11:19

    Searchでは? あと、前の質問はちゃんと削除リクエストできましたか?(ゴミ箱ボタンからリクエストを送れます)

    キャンセル

  • lianprivate

    2018/12/21 11:21

    hayatakaさん
    Searchですね・・・。根本的なミス、お恥ずかしい限りです。削除リクエストは既に行いました!ご心配頂きありがとうございます!

    キャンセル

  • hayataka2049

    2018/12/21 14:11

    削除リクエストを出すと、

    この質問は、一時的に非表示にされています
    質問者から削除リクエストが行われたため、運営チームで確認を行っています。
    申し訳ありませんが、確認が終わるまでしばらくお待ち下さい。

    のような表示に切り替わり、新着の質問欄などからも見れなくなるはずなので、何かしら上手く行っていない可能性があります。まだ質問が見れる状態のようなので・・・。

    キャンセル

回答 3

checkベストアンサー

+3

クラスやメソッドの基本的な考え方は「役割分担」です。
同じような記述をしているのであれば、そこはメソッドとして切り出して、可変的なところと固定的なところを決めて
可変的なところを引数で対応します。

今回の処理内容ですと、
//接続文字列 から //PostgreSQLへ接続 までの一連の手続きは固定です。
その先の処理はConnectionだけあれば良いので、接続処理はまとめましょう。

ここで問題となるのがSerchというクラスの「役割」です。
Connection自体は検索に限らず、新規追加・更新・削除 でも使います。
そして、もしかしたら「検索」という処理自体も様々なところで使えますし、
m_user以外のテーブルで利用することもあるかもしれません。

ということは、今の作りだとそのたびにクラスが増えるということになりますね。
「Serch」という名前も相応しくなくなります。
そこでやはりMVCのMである「モデル」の考え方が必要になってくると思います。

色々と解釈はありますが「データを取り扱うAPI」としての利用方法が一般的には多い印象です。

つまり、例えばUserというクラスを作り、そこで今回のテーブルで言えばm_userに関する
処理全てを書く というやり方ですね。

ただ、ここで注意点があります。
m_userはあくまでデータテーブルの1つであり、最上位ではないということ。
並列で並ぶのは他のテーブルです。
では、最上位とは何か。

「データベースを取り扱う」そのものです。

DB接続もそう、検索・新規追加・更新・削除 もそうです。
もっと言えば、「検索・新規追加・更新・削除」も共通しているのは
SQLを実行してexecuteQueryして結果を得ているということ。
得た結果をどう取り扱うかは違いますが、結局のところResultSetを受け取っています。

つまり、各テーブル用のクラスにその最上位のクラスを継承させることで、
より汎用的な作りが可能となります。

今回提示されているコードは検索のコードなので、そこにもフォーカス宛てますと、
確かに取得する列やWhere句の条件は違いますが、最終的にはSELECT文を発行しています。

ここで私の回答の最初に立ち戻りましょう。
「役割分担」のところですね。
「同じような記述をしているのであれば、そこはメソッドとして切り出して、可変的なところと固定的なところを決めて
可変的なところを引数で対応します。」のところですね。

うまく引数を使えば、如何様にも対応が可能です。
検索するカラムやカラムの型、検索の方法(完全一致、部分一致) このあたりを
例えば配列で渡してその内容によってWhere句を作るようにすればメソッド1つでどのようなSELECTにも対応が可能です。
もちろん汎用メソッドを作るのは作ってそちらを呼び出せば良いですが、それだけだと呼び出すときに意図がもてなかったり、
毎回配列を作るのが大変だったりします。
今回提示されたLatestDateですとかSerchIDのように「特定の情報を取得する場合」ですね。
その場合は、それ専用のメソッドを用意しておき、そのメソッドの中で検索用の配列を作り、
汎用メソッドを呼び出すような仕組みにすることで、専用メソッドを呼び出すだけで特定の動作をしてくれるように作ります。

という感じで。
他の更新や削除についても同じように考えてみてください。
「役割分担」「共通化」ですね。

メソッドの引数は情報が増えれば増えるほど、引数が多くなりすぎるようなイメージがあるかもしれませんが、
配列を使うことで、そこをスマートに対応することもできるようになります。
分岐が増えることにもなるのでそこはメソッド自体も太り過ぎないように気をつける必要はありますが、
汎用メソッドと専用メソッドをうまく使い分けることができれば、あまりFat Codeにはならないようにも思います。

そこは何度も組んで、組みなおして、リファクタリングしていくしかないですね。

ご参考まで。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/21 11:20

    いつもいつもありがとうございます!!
    正に私が欲していた答えを丸々頂いたような感じです!!
    今作っている流れが根本から変えていけるような答えでしたので、これからの学習が楽しくなってきました!
    本当にありがとうございます!頑張ります!

    キャンセル

  • 2018/12/21 11:28

    いろいろな意見を聞けるはずなのでもうちょっと待ってみても良かったのかなあとは思います。

    キャンセル

  • 2018/12/21 11:32

    (Javaコーディング規約については置いといて)
    英語の誤表記にはあえて触れませんでした。
    我々が対応しているのはプログラムであり、英語ではないので。
    まあでも「指示した通りしか動かない」という観点からスペルミスは命取りになり得るので間違えない方が良いのは言うまでもないですが。
    変に難しい英単語を使うよりはローマ字表記の方が分かりやすいという現場も少なくないですしね。

    キャンセル

  • 2018/12/21 11:36

    確かにおっしゃる通り、今回の質問は奥が深そうで、色々とご意見ありそうでですね。
    そんな現場もあるんですね、勉強になります!
    もうしばらくすると初の現場に入るので、そこで更にスキルアップできればと思っています。
    みなさんのご意見を参考にして少しでも迷惑掛からないよう精進していきます。ありがとうございます!

    キャンセル

  • 2018/12/21 11:44

    現場に入ってみないとわからないこともあるし、現場のルールもあります。
    まずは現場のルールをしっかり把握してコードに反映するようにしてください。
    初めての現場であれば必ず先輩がつくはずなので、分からないところは必ず確認するようにしてくださいね。
    質問の仕方はteratailのような聞き方が実は望ましかったりします(何も調べず試さずはNG。でも考えすぎ、自己判断もNGというバランス)

    キャンセル

  • 2018/12/21 12:04

    なかなかバランスが難しいですねw
    でもteratailを多分そこそこ上手く使えてると思うので(パスワードの件は除く)、現場に行ったらコミュニケーション大事にしてやってみます!また詰まったらその時は宜しくおねがいします!

    キャンセル

+3

1メソッドの長さは理想はスクロールせずに収まる長さまでとどこかで聞いたことがあります。

いいところまでいっているとは思いますが、私なら
DB接続するメソッド、1の更新をするメソッド、2の更新をするメソッド、3の更新をするメソッド
を作って、latestDateメソッドからそれぞれのメソッドをif文の分岐で呼び出すかな~と思います。

ただ、オブジェクト指向とはあまり関係ありませんが、Java的に宜しくないコーディングがいくつか見受けられるのでそこも書いておきます。

まず、メソッド名の先頭は小文字です。
今回ですと、LatestDate() → latestDate()です

あとは、文字(数字)の直書きは宜しくないです。
定数化したほうがよいと思います。

あとは超どうでもいいですが、 Serch()じゃなくて Search()・・・?かなと。

コーディング規則は超めんどくさいし、どうでもいいじゃん~!と思うかもしれませんが、現場に出るとかなり怒られます。
初期のうちに直せるところは直しておくと、後々困らないです。おすすめします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/21 11:26

    azuapricotさん
    ご指導、ご指摘ありがとうございます!
    そういったコーディング規則まで中々頭が回らないので、現場に入る前に教えて頂いてありがたい限りです!
    オブジェクト指向に関してもとても参考になりました!よく勉強します!英語に関しても勉強します・・・。
    ありがとうございました!

    キャンセル

+1

DB を SQL で直接操作してもよいですが、 DB 操作をあつかうためのライブラリーがいくつも存在しています。

こういったものをうまく使うと、簡潔に処理を記述できます。
敷居は高いかもしれませんが、小さいサンプルなどで勉強していき検討してみると学べる点が多くあると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/27 14:22

    これは良いことを聞きました!現場で利用できるかは別として、知識として今から勉強してみます!
    ありがとうございます!

    キャンセル

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

  • Java

    16139questions

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

  • オブジェクト指向

    331questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。