#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()). Вы определенно получаете ошибки. Вам нужно их найти.
Другое:
- Используйте локальные переменные вместо полей, где это уместно.
- Открывайте новое соединение при каждом запросе.
- Не закрывайте средство записи ответов (или OutputStream).
//Loads Driver
это ужасный комментарий. Остальные тоже не слишком хороши.- Никогда Не объединяйте строки непосредственно в SQL-запрос. Используйте PreparedStatement с заполнителями и методы set * для подключения параметров.
- Добавьте некоторое значимое ведение журнала, чтобы помочь вам определить, что происходит, без необходимости подключать отладчик. (Однако вам, очевидно, придется сначала выяснить, куда отправляются сообщения.)
- Вам нужно будет вызвать next() в результирующем наборе, прежде чем вы сможете получить из него значения.
- В
Class.forName(...)
строке нет необходимости. - Ваш набор результатов, оператор и / или соединение должны быть закрыты, когда вы закончите с ними. В противном случае вы ограничиваете ресурсы.
- Вместо того, чтобы перехватывать и игнорировать исключения, разрешите им выбрасываться из вашего сервлета. Это поможет вам в устранении неполадок.
- Никогда не перехватывайте исключение. Перехватывайте только те конкретные типы, которые вы хотите перехватить.
Комментарии:
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()
onResultSet
перед использованием методов 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. Я исправил проблемы, о которых он упоминал, за исключением использования слоев сохранения, это немного продвинуто для меня, мне нужно будет прочитать об этом.