【问题标题】:Java, code works, but exception is still thrownJava,代码有效,但仍然抛出异常
【发布时间】:2012-10-30 14:42:59
【问题描述】:

我正在创建一个简单的注册框架,用于将记录添加到数据库中。每次运行在数据库中添加记录的 SQL 查询时,它都会给我一条错误消息,但它仍然会添加它们,但因此我的程序会停止,而不是打开另一个窗口。

这是那部分代码:

regButton.addActionListener(new ActionListener() {

@Override public void actionPerformed( ActionEvent e ) {
   //Execute when button is pressed
   if(   uNameField.getText().equals("")
      || new String(newPassField.getPassword()).equals("")
      || new String(repeatPassField.getPassword()).equals("") ) {
      errorLabel.setForeground(Color.red);
      errorLabel.setText("Some fields are left blank");
   }
   else if( new String(newPassField.getPassword()).equals(
            new String(repeatPassField.getPassword()))){
      Statement stmt;
      ResultSet res;
      try
      {
         //SET USERNAME AND PASSWORD FROM FIELDS TO UPPER CASE
         String username = uNameField.getText().toUpperCase();
         String password = new String(newPassField.getPassword()).toUpperCase();
         //SQL INSERT QUERY
         String sql;
         sql = "INSERT INTO Employees VALUES ('" +username +"','" +password +"');";
         stmt = con.createStatement();
         res = stmt.executeQuery(sql);
         System.out.println("Added to database!");
         con.close();
      }
      catch(SQLException exe) {
         System.out.println("Error creating or running statement: " + e.toString());
         try {
            con.close();
         }
         catch(Exception eex){}
      }
   }
   else {
      errorLabel.setForeground(Color.red);
      errorLabel.setText("Password missmatch");
   }
}

每次注册新员工(用户)时,它都会显示此“创建或运行语句时出错:.....”虽然,我可以在员工列表中找到新添加的员工。

什么可能导致这个问题?

【问题讨论】:

  • 您能否打印您正在吞咽的异常的堆栈跟踪并将其添加到您的问题中?
  • 能否请您使用变量exe打印堆栈跟踪

标签: java sql exception


【解决方案1】:

为什么不试试 PreparedStatement

try{
    //SET USERNAME AND PASSWORD FROM FIELDS TO UPPER CASE
     String username = uNameField.getText().toUpperCase();
     String password = new String(newPassField.getPassword()).toUpperCase();
     //SQL INSERT QUERY
     PreparedStatement pstmt = con.prepareStatement("insert into Employees values(?,?)");
     pstmt.setString(1,username);
     pstmt.setString(2,password);

     if(!pstmt.execute())
     {
       //means your code worked correctly
        System.out.println("Inserted successfully");
     }
     else
     {
           System.out.println("Unsuccessfull");
     }
   }
   catch(Exception ex)
   {
      ex.printStackTrace();
   }

【讨论】:

    【解决方案2】:

    在我们解决您的具体问题之前,请提供一些一般性建议:

    Connection con = ...
    try {
        // your stuff
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    finally {
      try {
        con.close();
      } catch (Exception e) {
       e.printStackTrace();
      }
    }
    

    您现在这样做的方式不仅可以吞下异常,还可以避免打印其堆栈跟踪。并且close 必须执行一次且只执行一次,无论是否有异常。

    如果您使用的是 Java 7,这会容易得多:

    try (Connetion con = ...) {
      // stuff to do
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    

    finally 中的关闭现在自动完成。

    特别是关于您的异常,您通过调用 executeQuery 执行 INSERT。此方法将语句发送到 DB,它会正确执行它,但它对 JDBC 的响应不是 ResultSet。这就是它爆炸的地方,在记录已经插入之后。由于您处于自动提交模式,因此没有要回滚的事务。教训:始终使用事务

    【讨论】:

    • @Aubin 当然,如果 OP 可以使用的话。
    【解决方案3】:

    SQL INSERT 需要使用 executeUpdate

    int rowCount = stmt.executeUpdate(sql);
    

    【讨论】:

    • 当我更改它时,我在该行收到一条错误消息“不兼容的类型,需要 java.sql.ResultSet,找到 Int
    【解决方案4】:

    我讨厌看到这样写的代码。你没有问这个问题,我的评论也解决不了你的问题,但我觉得有必要说一下。

    通过将持久性代码放入 Swing 侦听器方法,您正在为自己制造维护噩梦。

    更好的想法是以赋予它们单一职责的方式来考虑对象。

    将您的持久性代码移到一个单独的类中,您可以自行开发和测试。一旦它工作了,给需要它的类一个引用。

    您的代码将更加模块化、更易于测试、更可重用并且理解起来不会像噩梦一样。

    鲍勃·马丁叔叔对这个和其他值得记住的想法有一个简洁的记忆:SOLID

    【讨论】:

    • 这段代码很可能不会被维护,但现在开始学习正确的方法永远不会太早。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多