resultSet.rowUpdated () выбрасывает исключение createSQLFeatureNotSupportedException - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь обновить строку в базе данных.Все остальное работает нормально, удаляя, создавая, перечисляя, но редактирование строки дает мне исключение createSQLFeatureNotSupportedException

@Override
    public Boolean editarUsuario(Usuario usuario) throws SQLException {
        try(Connection connection = MySqlConnection.abrirConexao()){
            Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

            ResultSet resultSet = statement.executeQuery("select * from usuario where idUsuario = " + usuario.getIdUsuario());

            if (resultSet.first()) {
                resultSet.updateInt("IdUsuario", usuario.getIdUsuario());
                resultSet.updateString("Login", usuario.getLogin());
                resultSet.updateString("Senha", usuario.getSenha());
                resultSet.updateBoolean("Admin",usuario.isAdmin());
                resultSet.updateBoolean("Operador",usuario.isOperador());
                resultSet.updateBoolean("Cliente",usuario.isCliente());
                resultSet.updateRow();
                return resultSet.rowUpdated();
            }

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

        return false;
    }

Эта строка [return resultSet.rowUpdated();] дает мне это исключение.Я просто хочу обновить строку.

Что я делаю не так?

Вот мой MySqlConnection

public class MySqlConnection {
    public static String url = "jdbc:mysql://localhost:3306/webticket?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
    public static String usuario = "root";
    public static String senha = "123456";

    public static Connection abrirConexao() throws SQLException {
        DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
        return DriverManager.getConnection(url, usuario, senha);
    }
}

А вот и исключение:

04-Dec-2018 09:00:36.294 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\DevTools\apache-tomcat-9.0.12\webapps\manager]
04-Dec-2018 09:00:36.344 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\DevTools\apache-tomcat-9.0.12\webapps\manager] has finished in [49] ms
java.sql.SQLFeatureNotSupportedException
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLFeatureNotSupportedException(SQLError.java:236)
    at com.mysql.cj.jdbc.result.UpdatableResultSet.rowUpdated(UpdatableResultSet.java:1183)
    at br.edu.fapi.webticket.usuario.dao.impl.UsuarioDAOImpl.editarUsuario(UsuarioDAOImpl.java:125)
    at br.edu.fapi.webticket.usuario.dao.impl.OperadorDAOImpl.editarUsuario(OperadorDAOImpl.java:22)
    at br.edu.fapi.webticket.usuario.web.OperadorEditar.doPost(OperadorEditar.java:51)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

Есть идеи, как ее решить?

Ответы [ 4 ]

0 голосов
/ 04 декабря 2018

Это похоже на ошибку в реализации MySQL Connector / J.Метод ResultSet.rowUpdated() является необязательным только для CONCUR_READ_ONLY наборов результатов, но, очевидно, MySQL Connector / J неверно истолковал это как «метод является необязательным» и просто реализовал его, чтобы всегда выдавать SQLFeatureNotSupportedException (см. UpdatableResultSet.rowUpdated в источниках MySQL Connector / J).

Я предлагаю вам сообщить об ошибке в MySQL.

Из ResultSet.rowUpdated() apidoc (в частности, Примечание ):

Получает информацию об обновлении текущей строки.Возвращаемое значение зависит от того, может ли результирующий набор обнаруживать обновления.

Примечание : поддержка метода rowUpdated является необязательной с параллелизмом набора результатов CONCUR_READ_ONLY

Возвращает :
true, если обнаружено, что текущая строка была визуально обновлена ​​владельцем или другим лицом;false в противном случае
Броски :
SQLException - если возникает ошибка доступа к базе данных или этот метод вызывается для закрытого набора результатов
SQLFeatureNotSupportedException - если драйвер JDBC делаетне поддерживает этот метод

В качестве решения (или обходного пути) я предлагаю заменить return resultSet.rowUpdated(); на return true;.При успешном выполнении resultSet.updateRow() вы можете быть уверены, что обновили строку (хотя, возможно, вы обновили ее с теми же значениями, которые у нее уже были).

Тем более что rowUpdated, учитывая определение, необязательно сообщите, что вы думаете, что он делает.Он используется главным образом для обнаружения одновременных видимых обновлений при прокрутке, а не для обнаружения ваших собственных явных обновлений.Смотрите также DatabaseMetaData.updatesAreDetected.

0 голосов
/ 04 декабря 2018

Сначала вы можете попытаться изменить свой запрос в запросе на обновление:

statement.executeQuery("update usuario set IdUsuario = " 
                      + usuario.getIdUsuario() + ", Login=" + usuario.getLogin()
                      + "where idUsuario = "+ usuario.getIdUsuario());

В приведенном выше коде я показал, как это сделать для первых двух полей, но вы можете добавить все необходимые поля.

Объяснение: не все драйверы JDBC поддерживают метод updateRow().Вот почему вы получаете это исключение, ваш текущий драйвер не поддерживает этот метод.Лучше использовать оператор UPDATE.Таким образом, вы увидите, как работает обновление для каждого используемого вами драйвера JDBC.

Также: не используйте конкатенацию строк для составления запросов.Он подвергается SQL-инъекции.Используйте PreparedStatement правильно, чтобы избежать такого рода уязвимости в вашем коде.Как следующее:

PreparedStatement ps = connection.prepareStatement(
  "UPDATE usuario SET IdUsuario = ?, Login= ? WHERE idUsuario = ?");
ps.setInt(1,usuario.getIdUsuario());
ps.setString(2, usuario.getLogin());
ps.setInt(3,usuario.getIdUsuario());
ps.executeUpdate();
ps.close(); //<- always close PreparedStatement when you are done
0 голосов
/ 04 декабря 2018

Обновление строки таблицы: как это делается с использованием JDBC API.Обратите внимание на использование PreparedStatement и метода executeUpdate:

String DML = "UPDATE usuario " +
             "SET IdUsuario = ?, " +
                  "Login = ?, " +
                  "Senha = ?, " +
                  "Admin = ?, " +
                  "Operador = ?, " +
                  "Cliente = ? " +
             "WHERE idUsuario = ?";

try (PreparedStatement pstmt = connection.prepareStatement(DML)) {

    pstmt.setInt(1, usuario.getIdUsuario()); 
    pstmt.setString(2, usuario.getLogin()); 
    pstmt.setString(3, usuario.getgetSenha());  
    pstmt.setBoolean(4, usuario.getisAdmin()); 
    pstmt.setBoolean(5, usuario.isOperador());
    pstmt.setBoolean(6, usuario.isCliente());
    pstmt.setBoolean(7, usuario.getIdUsuario());

    int noOfRowsUpdated = pstmt.executeUpdate();
}
catch(SQLException ex) {
    // handle the exception here...
}


ПРИМЕЧАНИЕ. Предполагается, что столбец IdUsuario является первичным ключом таблицы - в этом случае ивам не нужно заново устанавливать его значение во время обновления.

0 голосов
/ 04 декабря 2018

попробуйте обновить драйвер jdbc в соответствии с вашей версией mysql

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...