Мне нужно некоторое руководство по доступу к mysql с использованием Java servlet

#java #mysql #servlets

#java #mysql #сервлеты

Вопрос:

Вот мой код

 import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.sql.*;

@WebServlet(name = "Scores", urlPatterns = {"/Scores"})
public class Scores extends HttpServlet{

    private Connection conn;
    private PreparedStatement psmt;
    private ResultSet rs;
    private String tableName;
    private String ssnNum;

    @Override
    public void init() throws ServletException {
        connect();
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        try{
            tableName = request.getParameter("tableName");
            ssnNum = request.getParameter("ssnNum");

            rs = psmt.executeQuery();

            out.print("ttt");
            out.print(rs.getString("Student")   " "   rs.getString("Score"));
            out.print("<br>");
            out.close();
        }catch(Exception e){
            System.err.println(e);
        }
    }

    public void connect(){
        try{
            //Loads Driver
            Class.forName("com.mysql.jdbc.Driver");

            //Establishes a connection to DataBase Javabook
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost/javabook", "root", "password");

            psmt = conn.prepareStatement("select Student, Score from "   tableName   
                    " where ssn = "   ssnNum);
        } catch (Exception e){
            System.err.println(e);
        }//End Try/Catch Block
    }
}
  

Вот html

 <%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>TravisMeyersP3</title>
    </head>
    <body>
        Find Your Current Score
      <form method = "get" action = "Scores">
      <p>Social Security Number <font color = "#FF0000">*</font>
         <input type = "text" name = "ssnNum">
      </p>
      <p>Course Id
         <select size = "1" name = "tableName">
           <option value = "Cpp">C  </option>
           <option value = "AdvJava">Advanced Java</option>
         </select>
      </p>
      <p><input type = "submit" name = "Submit" value = "Submit">
      </p>
    </body>
</html>
  

Я использую apache tomcat 7.0.21 и Java jdk 7 в netbeans. Предполагается, что сервлет обращается к одной из двух таблиц, которые я создал в mysql, и отображает значения пользовательских параметров. Я не получаю никаких ошибок компиляции или времени выполнения. По какой-то причине сервлет не обращается к mysql и не отображает результат после отправки формы пользователем.


Прежде всего, я должен поблагодарить Райана Стюарта, элитного джентльмена и CodeBuzz за то, что они нашли время, чтобы помочь мне. Наряду с вышеупомянутыми проблемами у меня также была проблема с синтаксисом sql. Поскольку я устанавливаю переменные tableName и ssnNum в моем новом PreparedStatement (PreparedStatement psmt = conn.prepareStatement («выберите ученика, оценка от? где SSN = ?;»);) используя psmt.setString(1, tableName) и т.д. по какой-то причине это заключало строку в одинарные кавычки в подготовленном операторе. MySQL это не понравилось, и единственное место, которое показывало ошибку, было в окне командной строки tomcat. После устранения вышеупомянутых проблем все работало отлично. Еще раз спасибо всем за помощь мне в этом.

Комментарии:

1. Открывать соединение при инициализации сервлета и оставлять его открытым — плохая идея.

2. Ох. Вы правы. Я это исправлю. Спасибо.

3. Сервлеты не являются потокобезопасными, поэтому не должны иметь никакого состояния. Так, например, ваше поле tablename может быть перезаписано другим потоком, который обрабатывает другой HTTP-запрос, с неожиданными результатами.

Ответ №1:

Это никак не может сработать. При инициализации() вы создаете PreparedStatement, используя запрос, который включает поля tableName и ssnNum . В этот момент оба они равны нулю. Они не назначаются до тех пор, пока запрос не будет сделан позже (в doGet()). Вы определенно получаете ошибки. Вам нужно их найти.

Другое:

  1. Используйте локальные переменные вместо полей, где это уместно.
  2. Открывайте новое соединение при каждом запросе.
  3. Не закрывайте средство записи ответов (или OutputStream).
  4. //Loads Driver это ужасный комментарий. Остальные тоже не слишком хороши.
  5. Никогда Не объединяйте строки непосредственно в SQL-запрос. Используйте PreparedStatement с заполнителями и методы set * для подключения параметров.
  6. Добавьте некоторое значимое ведение журнала, чтобы помочь вам определить, что происходит, без необходимости подключать отладчик. (Однако вам, очевидно, придется сначала выяснить, куда отправляются сообщения.)
  7. Вам нужно будет вызвать next() в результирующем наборе, прежде чем вы сможете получить из него значения.
  8. В Class.forName(...) строке нет необходимости.
  9. Ваш набор результатов, оператор и / или соединение должны быть закрыты, когда вы закончите с ними. В противном случае вы ограничиваете ресурсы.
  10. Вместо того, чтобы перехватывать и игнорировать исключения, разрешите им выбрасываться из вашего сервлета. Это поможет вам в устранении неполадок.
  11. Никогда не перехватывайте исключение. Перехватывайте только те конкретные типы, которые вы хотите перехватить.

Комментарии:

1. ОК. Это сложно понять, но я это исправлю.

2. Что касается # 5, вы можете начать читать о внедрении SQL в Википедии и XKCD .

3. psmt = conn.prepareStatement («выберите ученика, оценка от ? где ssn = ?»); psmt.setString(1, имя таблицы); psmt.setString(2, ssnNum);

Ответ №2:

Ваше объявление HTML <form> неверно:

 <form method = "get" action = "Scores">
  

Вот несколько решений ваших ошибок выше:

  • Ваш метод должен быть GET , а не get (следуйте методам HTTP).
  • Ваше действие должно быть /Scores , а не Scores .
  • Вам нужно вызвать next() on ResultSet перед использованием методов getXXX (где XXX может быть Int , String , Double и т.д.).
  • Всегда закрывайте ResultSet сначала, затем Statement / PreparedStatement и, наконец, Connection .

Кроме того, я бы посоветовал никогда этого не делать:

  • Никогда не разрешайте подключения к сервлетам вообще. Вы открываете соединение на init() , что плохо, поскольку соединение может истекать или закрываться, и вы никак не можете его открыть (сервлеты являются одиночными).
  • Кроме того, я бы предложил использовать PreparedStatement вместо объединения строк. Драйвер знает, как преобразовать типы данных в соответствующие типы SQL.

Я бы посоветовал вам создать уровень сохраняемости, который следует простым операциям CRUD с базой данных.

Ответ №3:

вы подготовили оператор запроса в init() функции, где вы не получили никакой записи из-за
нулевого значения в tableName и ssnNum .
поэтому измените это и подготовьте запрос, когда вы получили функцию response in doGet() , после чего выполните ее.

Ответ №4:

Создайте подготовленный оператор в методе doGet вместо метода connect.`

  @Override

     public void doGet(HttpServletRequest request, HttpServletResponse
        response) throws ServletException, IOException {

    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    try{
        tableName = request.getParameter("tableName");
        ssnNum = request.getParameter("ssnNum");
        psmt = conn.prepareStatement("select Student, Score from ? where ssn = ?");
        psmt.setString(1,tableName);
        psmt.setString(2,ssnNum);
        rs = psmt.executeQuery();

        out.print("ttt");
        out.print(rs.getString("Student")   " "   rs.getString("Score"));
        out.print("<br>");
        out.close();
    }catch(Exception e){
        System.err.println(e);
    }
}

public void connect(){
    try{
        //Loads Driver
        Class.forName("com.mysql.jdbc.Driver");

        //Establishes a connection to DataBase Javabook
        conn = DriverManager.getConnection(
                "jdbc:mysql://localhost/javabook", "root", "password");


    } catch (Exception e){
        System.err.println(e);
    }//End Try/Catch Block
}
  

`

Лучшим подходом было бы создание бизнес-класса, который заботится о подключении к базе данных и использует этот класс из сервлета. Смотрите Выбор записей с использованием PreparedStatement

Комментарии:

1. ОК. Я исправил проблемы, о которых вы, ребята, упоминали. Все тот же результат. Когда я отправляю форму, я получаю пустую страницу. ???

2. Изначально у меня был подготовленный оператор в методе doget. Я поместил его в метод connect, потому что я просто пытался заставить его работать.

3. Я исправил проблемы, о которых он упоминал, за исключением использования слоев сохранения, это немного продвинуто для меня, мне нужно будет прочитать об этом.