我尝试使用以下代码将数据输入MySQL数据库。任何帮助都将非常感激,因为我无法解决为什么会有异常。请求参数由HTML表单提供,并且根本不存在任何问题,数据通过就好了。这个问题似乎发生在servlet完成之后,可能在DAO或连接管理器中的某个地方。非常感谢!
相关Servlet代码:
UserRegistrationBean user = new UserRegistrationBean();
user.setUsername(request.getParameter("Username"));
user.setPassword(request.getParameter("Password"));
user.setEmail(request.getParameter("Email"));
user = UserDAO.register(user);
if (user.getExists() == true) {
ErrorMessage = "The user name you entered has already been registered!";
request.setAttribute("ErrorMessage", ErrorMessage);
request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);
return;
}
UserDAO的:
public static UserRegistrationBean register(UserRegistrationBean bean) {
Statement stmt = null;
String username = bean.getUsername();
String password = bean.getPassword();
String email = bean.getEmail();
String searchQuery = "SELECT * FROM tblusers WHERE Username='"
+ username
+ "'";
String insertQuery = "INSERT INTO tblUsers (Username, Password, Email) VALUES ('"
+ username +
"', '"
+ password +
"', '"
+ email +
"')";
try {
currentCon = ConnectionManager.getConnection();
stmt = currentCon.createStatement();
//check if user exists
ResultSet searchRs = stmt.executeQuery(searchQuery);
//User name is available
if (searchRs.next() == false) {
bean.setExists(false);
}
//User name is not available
else if (searchRs.next() == true) {
bean.setExists(true);
}
if (bean.getExists() == true) {
//Return error and prevent registration
bean.setSuccess(false);
return bean;
}
else {
stmt.executeUpdate(insertQuery);
bean.setSuccess(true);
}
}
catch(Exception ex) {
//exception available here
}
return bean;
}
的ConnectionManager:
public class ConnectionManager {
static Connection connection;
static String url;
public static Connection getConnection() {
try {
String url = "jdbc:odbc:" + "localhost:3306";
Class.forName("com.mysql.jdbc.Driver");
try {
connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/the_atrium_beauty?"
+ "user=System&password=sYstem~9");
}
catch (SQLException ex) {
//Stack trace available here
//ex.printStackTrace();
}
}
catch(ClassNotFoundException e) {
//Exception check available here
//System.out.println(e);
}
return connection;
}
}
尝试Catch Block:
catch(Throwable exception) {
String errorMessage = exception.getMessage();
Throwable errorCause = exception.getCause();
String errorLocation = this.getServletName();
request.setAttribute("ErrorMessage", errorMessage);
request.setAttribute("ErrorCause", errorCause);
request.setAttribute("ErrorLocation", errorLocation);
request.getRequestDispatcher("/WEB-INF/errorDisplay.jsp").forward(request, response);
}
错误显示JSP:
<body>
<% final String errorMessage = (String)request.getAttribute("ErrorMessage"); %>
<% final Throwable errorCause = (Throwable)request.getAttribute("ErrorCause"); %>
<% final String errorLocation = (String)request.getAttribute("ErrorLocation"); %>
<h1>An Error Occurred...</h1>
<p>
<%= errorMessage %><br><br>
<%= errorCause %><br><br>
<%= errorLocation %>
</p>
</body>
堆栈追踪:
java.lang.NullPointerException
at com.atrium.userServlets.UserRegistrationServlet.doPost(UserRegistrationServlet.java:231)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:1)
我认为你的问题在于此处(为了便于阅读而略微浓缩代码):
ResultSet searchRs = stmt.executeQuery(searchQuery);
//User name is available
if (searchRs.next() == false) {
bean.setExists(false);
}
//User name is not available
else if (searchRs.next() == true) {
bean.setExists(true);
}
if (bean.getExists() == true) {
//Return error and prevent registration
bean.setSuccess(false);
return bean;
}
next()
将ResultSet
的内部光标移至下一行。这意味着后续对next()
的调用不能保证返回相同的结果。
所以这个:
if (searchRs.next() == false) {
以后几行可能不会返回相同的东西:
else if (searchRs.next() == true) {
这意味着通过此代码存在潜在的途径,其中 条件都不是真的。具体来说,如果next()
的第一次调用返回true
而第二次调用返回false
,则两个分支都不会执行。
有很多方法可以解决这个问题。我个人会这样做:
// Check the true condition first, no need for == true
if (searchRs.next()) {
// User already exists
bean.setExists(true);
bean.setSuccess(false);
// Returning the bean object isn't strictly necessary because of side-effects
return bean;
} else {
// User doesn't already exist
bean.setExists(false);
stmt.executeUpdate(insertQuery);
// You'll need to commit the transaction for it to work properly:
currentCon.commit();
bean.setSuccess(true);
return bean;
}
基本上,由于此上下文中的boolean
比较只能有两个结果,因此您可以使用if {} else {}
代替if {} else if {}
。
注意:我假设getExists()
的返回类型为Boolean
而不是boolean
(因为boolean
不能{ {1}})。考虑到这一点,我认为由于上述问题,您没有初始化null
后面的变量,所以它仍然设置为默认值,对象为getExists()
。
由于对null
的更改为side effects,您实际上不需要从方法返回,对对象的更改也应该在方法外部可见。
对于你的异常处理,如果你没有报告它就不会吞下它,那将是非常有用的。据推测,调用方法需要知道一些不寻常的错误,所以不要抓住什么也不做,而是做这样的事情:
bean
其中try {
// Your database access code here
} catch (SQLException e) {
// You don't want to persist any dud data, so rollback the connection
currentCon.rollback();
// Propagates the exception upward to the calling method
throw new RegistrationException("Error registering user", e);
}
是您自己创建的自定义异常类(您应该至少定义一个以RegistrationException
和String
作为参数的构造函数。您还必须修改方法签名以声明异常:
Throwable
这会强制调用方法重新抛出(从而进一步传播)异常或处理它。
答案 1 :(得分:0)
您使用的是非常旧的type-1 sun.jdbc.odbc.JdbcOdbcDriver
,这对所有数据库都很常见,并且它也存在许多问题。所以我的建议是使用特定于数据库的驱动程序并相应地更改连接URL。
对于Ex:
如果您使用的是mysql,请使用
// this will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// setup the connection with the DB.
connect = DriverManager
.getConnection("jdbc:mysql://<ip>/<db name>?"
+ "user=<username>&password=<password>");