【问题标题】:Servlet - MySQL ErrorServlet - MySQL 错误
【发布时间】:2026-01-07 21:20:08
【问题描述】:

我正在尝试使用以下代码将数据输入 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;

            }

用户DAO:

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;

}

连接管理器:

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(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)

【问题讨论】:

  • 你说你得到一个错误,但你没有告诉我们它是什么,并且没有堆栈跟踪可供我们使用。您能否更新您的问题并向我们提供这些问题?此外,作为观察,您正在使用 executeQuery() 而不是 executeUpdate() 执行 update 语句。
  • 发布你的错误堆栈跟踪。
  • 你真的应该做一些有异常的事情,至少在某个地方打印出来!
  • 为什么不使用 com.mysql.jdbc.Driver 作为数据库驱动程序? sun.jdbc.odbc.JdbcOdbcDriver 非常过时,应该避免使用。
  • 现在将进行这些更改,我目前获取异常的方法有问题,我正在尝试修复它。将尽快提出异常消息。

标签: java mysql servlets


【解决方案1】:

您使用的是非常旧的 type-1 sun.jdbc.odbc.JdbcOdbcDriver,这对所有数据库都很常见,它也有很多问题。所以我的建议是使用特定于数据库的驱动程序并相应地更改连接 URL。

例如:

如果你使用的是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>");

【讨论】:

  • 是的,看起来还可以。那么现在有什么问题?
  • 好的,我正在尝试如何让我的 tomcat(在 eclipse 中)向我显示异常,它不会在调试模式下启动。我目前还有另一个关于我的自定义异常 jsp 的问题,如果我可以让它工作,那么我将能够为你提供一个异常,告诉你出了什么问题。每当我提交这个 HTML 表单时,我都会收到一个错误,我需要识别它。
  • 似乎你有一堆问题,但你没有分享任何一个。共享异常和错误堆栈跟踪,然后我们就可以了解出了什么问题。
  • 这是目前的问题,我正在尝试获取异常和堆栈跟踪但无法。这显示了我遇到的问题:*.com/questions/23267506/…
  • 我在问题中添加了堆栈跟踪。
【解决方案2】:

我认为您的问题出在此处(为了便于阅读,稍微压缩了代码):

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不能是null)。考虑到这一点,我相信您没有初始化 getExists() 后面的变量,因为上面的问题,所以它仍然设置为其默认值,对于对象,它是 null

因为对bean 的更改是side effects,所以您实际上不需要从方法中返回它,对对象的更改也应该在方法之外可见。


对于您的异常处理,如果您在不报告的情况下不吞下它,它将(非常)有用。大概调用方法需要知道有什么不寻常的地方出错了,所以与其捕捉并什么都不做,不如做这样的事情:

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 是您自己创建的自定义异常类(您应该至少定义一个以StringThrowable 作为参数的构造函数)。您还必须修改方法签名以声明异常:

public static UserRegistrationBean register(UserRegistrationBean bean)
        throws RegistrationException {

这会强制调用方法要么重新抛出(从而进一步传播)异常,要么对其进行处理。

【讨论】:

  • 那里的答案很棒,非常详细,我确信它为我解决了部分问题,但仍然发生相同的错误。某处仍然有问题。 SQL 查询是否无法正确执行并因此不返回结果集?
  • @TOFFster 如果查询没有正确执行,我希望看到一些关于SQLException 的描述被抛出。当您一揽子捕捉然后什么都不做(总是一个坏主意)时,第一个语句完全有可能失败,从而使您的 Boolean 未初始化。您能否向上传播异常或打印堆栈跟踪,看看会发生什么?
  • 问题中的堆栈跟踪是当前正在生成的堆栈跟踪。传播异常是什么意思?
  • @TOFFster 在catch 块中,与其什么都不做,不如重新抛出异常,可能会添加您自己的消息(也可能使用自定义异常)。我会用一个建议来更新我的答案。
  • 好的,谢谢。我仍然不能 100% 确定你的意思,但我希望这个例子能对它有所启发。