Как поймать нарушение ограничений внутри цикла результирующего набора?

#java #jdbc

#java #jdbc

Вопрос:

Я работал над сервлетом, который будет генерировать уникальный код и обновлять его в базе данных MySQL. Теперь, в этом случае, я хочу перехватить любое исключение, выданное в случае, если этот уникальный код уже существует в таблице MySQL, сгенерировать новый код и попытаться обновить базу данных. Проблема в том, что я хочу сделать это В самом цикле for. Код выглядит следующим образом:

     try
    {
    connection = datasource.getConnection();
    SQLUpdate = "INSERT INTO Voucher_dump VALUES( '" unique_code "','08-10-2011 04:48:48','0')";
      PreparedStatement ps1 = connection.prepareStatement(SQLUpdate);
      ps1.executeUpdate();
      ResultSet r = ps1.getResultSet(); // this is where I'm checking if it's a duplicate
      if(r==null)
          out.println("This is a duplicate");
      else out.println("Updated");
      trial12= "08-10-2011 04:48:480.03999855056924717a";
      SQLUpdate = "INSERT INTO Voucher_dump VALUES( '" trial12 "','08-10-2011 04:48:48','0')";

      ps1 = connection.prepareStatement(SQLUpdate);
      ps1.executeUpdate();
      r = ps1.getResultSet();
      if(r==null)
          out.println("This is a duplicate");
      else out.println("Updated");

    }
    catch (SQLException sqle)
    {
        sqle.printStackTrace();
    }
  

Я не хочу ждать до конца всего цикла, чтобы перехватить исключение SQLException (я уже определил этот ключ в MySQL как основной). В тот момент, когда результат возвращается в виде повторяющейся записи, я хочу повторно сгенерировать этот ключ и повторить попытку обновления.Мой вывод для этого конкретного кода остается пустым на моей странице вывода (все остальные параметры отображаются правильно). Ни «Это дубликат» не отображается, ни «Обновляется». Возможно, ResultSet — не лучший способ сделать это. Не могли бы вы, ребята, дать мне несколько советов о том, что было бы наилучшим способом продвижения вперед?

Ответ №1:

Несколько советов в произвольном порядке:

  1. Закройте соединение в блоке finally.
  2. Закрывайте операторы по отдельности, если вы будете создавать многие из них перед закрытием соединения. («Много» определяется вашими администраторами баз данных.)
  3. Отформатируйте свой код.
  4. Не используйте стандартный вывод и / или стандартный вывод из реального кода. Выберите структуру ведения журнала.
  5. Рассмотрите возможность использования некоторых вспомогательных классов для упрощения (и исправления) доступа к базе данных, например JdbcTemplate от Spring.
  6. Обязательно включайте соответствующий контекст при публикации примера кода.

Из-за # 6 я не знаю, что out это такое, но я подозреваю, что причина, по которой вы ничего не видите, заключается в том, что вы вставляете повторяющееся значение с первым оператором, что вызовет исключение SQLException из этой строки, а не в getResultSet() , где вы, кажется, ожидаете этого. Поскольку ошибка записывается в стандартный вывод, она где-то появится в журналах вашего сервера, но ничего не будет записано out . Я не уверен, почему вы думаете getResultSet() , что вернет null или not null в зависимости от того, было ли нарушение ограничений. Взгляните на javadoc для этого метода.

Обновление: 7. Как указывает БалусК, никогда, никогда не объединяйте строку непосредственно в JDBC Statment. Используйте заполнители и set* методы PreparedStatment. Для получения информации о внедрении SQL см. Википедию и XKCD.

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

1. Потенциальная дыра в SQL-инъекции также может быть добавлена в список.

2. @BalusC: Ой. Хороший улов. Прошлой ночью я не спал слишком поздно.

Ответ №2:

Как насчет этого кода?

 try {
            Class.forName(driver).newInstance();
            conn = DriverManager.getConnection(url   dbName);
            System.out.println("Connected to the database");
            int i = 1;                                     //get the unique code
            boolean isInserted = false;
            while (!isInserted) {
                try {
                    PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO test values (?)");
                    preparedStatement.setInt(1, i);
                    preparedStatement.executeUpdate();
                    isInserted = true;
                } catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) {   //Catch the particular exception which throws error on unique constraint. This may depend on Java/MySQL your version 
                    i  ;                         //get the next unique code
                }
            }

            System.out.println("Disconnected from database");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (Exception e) {
            }
        }
  

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

1. Кажется, это решает проблему с постером, но, пожалуйста, не ловите Exception . Это может непреднамеренно перехватывать и отключать исключения, отличные от тех, которые вы хотите обработать. Вместо этого перехватите наиболее конкретный подкласс Exception.

2. Привет .. спасибо за всю вашу помощь…. попробую и дам вам знать.. Райан, я только что вставил ту часть кода, в которой я столкнулся с проблемами (1) и (2), которые уже были выполнены…. возьмет и другие …. большое спасибо!

3. Вы правы @S.L.Barth. Позаботится об этом в будущем. Спасибо за ваш ценный отзыв.