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

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

ただいまの
回答率

88.64%

ログイン機能登録について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,038

sususu

score 86

javaを勉強し始めて2カ月ほどです。
ログイン機能の勉強をしているのですが、新規登録のところで少し気になるところがあるので質問させていただきたいと思います。
下記のコード2種類書いたのですが一方は新規登録できますが、もう一方はできません。

ログイン機能の方はパラメータの値をDAOまで引数でもっていってからBEANに代入しているので
新規登録の方もDAOまで引数もっていってからしようとしましたができませんでした。エラーは出ていませんがJSPに遷移せずデータベースも反映されませんでした。原因は〇〇=execute〇〇のイメージがつかめていないからなのかと思っているのですが...

個人的にスッキリしないのはBEANに値を入れるタイミングが新規登録とログインで同じでない所なのですが、下記の「新規登録不可DAO」のコードの方を直すとすればどのように直せばよいのでしょうか?

見ずらいコードですみませんがご回答いただけると助かります。

新規登録可能サーブレット
package chat;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import bean.Customer;
import dao.CustomerDAO;

/**
 * Servlet implementation class Regist
 */
@WebServlet("/Regist")
public class Regist extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //doGet(request, response);
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");

        String login = request.getParameter("login");
        String password = request.getParameter("password");

        Customer customer = new Customer();
        customer.setLogin(login);
        customer.setPassword(password);

        CustomerDAO dao = new CustomerDAO();
        int line = 0;

            try {
                line = dao.insert(customer);
                if(line > 0){
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/regist-ok.jsp");
                    dispatcher.forward(request, response);
                }else{
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/regist-error.jsp");
                    dispatcher.forward(request, response);

                }
            } catch (Exception e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
    }
}
新規登録可能DAO
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import bean.Customer;

public class CustomerDAO extends DAO {
    public Customer search(String login,String password)throws Exception{//サーチメソッド

        bean.Customer customer = null;

        Connection con = getConnection();

        PreparedStatement st;
        st=con.prepareStatement("select * from customer where login = ? and password = ?");
        st.setString(1, login);
        st.setString(2, password);
        ResultSet rs = st.executeQuery();

        while(rs.next()){
            customer = new Customer();
            customer.setId(rs.getInt("id"));
            customer.setLogin(rs.getString("login"));
            customer.setPassword(rs.getString("password"));
        }
        st.close();
        con.close();
    return customer;
    }

    public int insert(Customer customer)throws Exception{//インサートメソッド

        Connection con = getConnection();

        con.setAutoCommit(false);

        PreparedStatement st= con.prepareStatement("insert into customer values(null,?,?)");
        st.setString(1, customer.getLogin());
        st.setString(2, customer.getPassword());
        int line = st.executeUpdate();

        if(line > 0){
            con.commit();
        }else{
            con.rollback();
        }

        st.close();
        con.close();
    return line;
    }
}
新規登録不可サーブレット
package chat;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.CustomerDAO_Error;

/**
 * Servlet implementation class Regist
 */
@WebServlet("/Regist_Error")
public class Regist_Error extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //doGet(request, response);
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");

        String login = request.getParameter("login");
        String password = request.getParameter("password");

        CustomerDAO_Error dao = new CustomerDAO_Error();
        int line = 0;

            try {
                line = dao.insert(login,password);
                if(line > 0){
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/regist-ok.jsp");
                    dispatcher.forward(request, response);
                }else{
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/regist-error.jsp");
                    dispatcher.forward(request, response);
                }

            } catch (Exception e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
    }
}
新規登録不可DAO
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import bean.Customer;

public class CustomerDAO_Error extends DAO {
    public Customer search(String login,String password)throws Exception{//サーチメソッド

        bean.Customer customer = null;

        Connection con = getConnection();

        PreparedStatement st;
        st=con.prepareStatement("select * from customer where login = ? and password = ?");
        st.setString(1, login);
        st.setString(2, password);
        ResultSet rs = st.executeQuery();

        while(rs.next()){
            customer = new Customer();
            customer.setId(rs.getInt("id"));
            customer.setLogin(rs.getString("login"));
            customer.setPassword(rs.getString("password"));
        }
        st.close();
        con.close();
    return customer;
    }

    public int insert(String login,String password)throws Exception{//インサートメソッド

        bean.Customer customer = null;

        Connection con = getConnection();

        con.setAutoCommit(false);

        PreparedStatement st= con.prepareStatement("insert into customer values(null,?,?)");
        st.setString(1, login);
        st.setString(2, password);
        ResultSet rs = st.executeQuery();
        int line = st.executeUpdate();

        while(rs.next()){
            customer = new Customer();
            customer.setId(rs.getInt("id"));
            customer.setLogin(rs.getString("login"));
            customer.setPassword(rs.getString("password"));
        }
        if(line > 0){
            con.commit();
        }else{
            con.rollback();
        }
        st.close();
        con.close();
    return line;
    }
}


開発環境
OS windows10
エディション enterprise
言語 java8.0.1310.11
MariaDB10.1
HeidiSQL
eclipse NEON

新規登録不可DAO while文部分コメントアウトに修正
PreparedStatement st= con.prepareStatement("insert into customer values(null,?,?)");
        st.setString(1, login);
        st.setString(2, password);
        ResultSet rs = st.executeQuery();
        int line = st.executeUpdate();

        //while(rs.next()){
            customer = new Customer();
            customer.setId(rs.getInt("id"));
            customer.setLogin(rs.getString("login"));
            customer.setPassword(rs.getString("password"));
        //}
        if(line > 0){
            con.commit();
        }else{
            con.rollback();
        }
        st.close();
        con.close();
    return line;
    }
}


イメージ説明

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

◆発生中の例外について
Lock wait timeout exceeded; try restarting transaction

  • このエラーは、「指定された行(またはテーブル)をupdate(またはinsert)しようとしたけど、ロックがかかっていて出来なかったよ。ロックが解除されるのを待ったけど時間切れだよ。」という意味です。

なぜ、あなたのDB内でロックがかかっているかはわかりませんが、開発してるときにたまにあります。(開発しててcommitするの忘れてかつ例外発生した時とか)

◆ロック解除の方法について
MariaDBをご利用とのことですので、DBクライアントソフト(GUIでDB内のデータを見れたり、GUIでデータ挿入できるツール)はHaidiSQLですかね?

【1】DBクライアントソフトは何でもいいですが、下記クエリ(SQL文のこと)を実行して、本当にロックがかかっているかたしかめましょう。このクエリで、現在存在するプロセスの一覧を出せます。
show processlist;

【2】プロセスの一覧が出せたら、ロックをかけていそうな怪しいプロセスを探しましょう。
DBクライアントソフトから操作している場合は、プロセスが全くないことは無いですので、あくまで怪しいやつ、です。

【3】怪しいプロセスがあったら、プロセスをkillしましょう。
プロセス一覧を出した時に、プロセスIDも一緒に表示されますので、怪しいプロセスをkillします。
kill 怪しいプロセスID

【4】作成したプログラムを動かしてみて、同じエラ-が発生するか確認しましょう。

これで発生しなければよいのですが、発生する場合やkillするプロセスがなさそうな場合は、スクショ等貼ってください。また見ますので。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/06 21:59 編集

    あと、実装おかしいところを指摘させてください。

    【1】
    insert処理では、executeQuery()、update処理ではexecuteUpdate()を使うのに、両方実装されています。新規登録であれば、insert処理と思われますので、前者のみ使うようにしましょう。
    ```
    ResultSet rs = st.executeQuery();
    int line = st.executeUpdate();
    ```

    【2】preparedStatement、connectionと同様に、resultSetにもclose処理が必要です。(まぁ、connectionさえちゃんと閉じれば、preparedStatementもresultSetも勝手に閉じますし、preparedStatementを閉じれば、resultSetは勝手に閉じますが、明示的に閉じた方が安全です)

    キャンセル

  • 2018/03/07 09:30

    色々ご指摘ご回答本当にありがとうございます。
    今回こちらのプロジェクトはほかのファイルもいろいろいじってしまったので、ちょっと復元が難しいですが、ソース以外の問題の可能性も教えていただいたのでベストアンサーとさせていただきます。
    resultSetのほうもこれから忘れずに閉じる明記していこうと思います。
    ありがとうございました!

    キャンセル

+2

新規登録不可DAOの、st.executeUpdate(); のあとに、while(rs.next()) をしているからです。

成功しているCustomerDAOではやっていません。
コードを相互比較すると、その違いがよくわかるかと思いますよ。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/23 19:28

    先ほど家につきましたので!早速試してみたいと思います!
    ご回答ありがとうございます!

    キャンセル

  • 2018/02/23 20:47

    ご指摘の通り(質問欄追記)修正したのですが、コンソールに下記のような表示が出てRegist_Errorで何も表示されず止まってしまいます。
    at java.lang.Thread.run(Thread.java:748)
    Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    Query is: insert into customer values(null,?,?), parameters ['oooo','oooo']
    at org.mariadb.jdbc.internal.util.LogQueryTool.exceptionWithQuery(LogQueryTool.java:153)
    at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:252)
    at org.mariadb.jdbc.MariaDbPreparedStatementClient.executeInternal(MariaDbPreparedStatementClient.java:209)
    ... 29 more
    調べてみたところテーブルのloginのカラムがユニークキーでダブり判定されてしまったと解釈しているのですが、テーブルを見るとそのような名前はなく以前も入れたことないような名前でも同じようなコンソールが表示されてしまいます。
    引き続き調べているところですが、何かお気づきの点ありましたらよろしくお願いします!!

    キャンセル

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

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

関連した質問

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