Почему логическое выполнение (String SQL) всегда верно, даже если мой ввод отсутствует в моей базе данных - PullRequest
0 голосов
/ 26 марта 2020

Это мой код

try{
    Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost/records";
    Connection con = DriverManager.getConnection(url,"root","");
    Statement st = con.createStatement();
    String sql = "SELECT * FROM patient_info WHERE name = '"+txt1.getText()+"' ";

, в этой части он всегда печатает true, если я прав, то это логическое значение возвращает логическое значение строки sql.

Boolean ret = st.execute(sql);
System.out.println(ret.toString());

это утверждение, если я не знаю, правильно ли

    if(ret == true){
        ResultSet rs = st.executeQuery(sql);
        String name = null;
        while(rs.next()) {
            name = rs.getString("name");
            txt2.setText(name);
            System.out.println("working"); 
        }
        rs.close();
    } else {
       txt2.setText("no records");
       System.out.println("no records");
    }
    st.close(); 
    con.close();

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

Ответы [ 2 ]

2 голосов
/ 26 марта 2020

Из JavaDo c:

логическое выполнение (String sql) выдает SQLException
Выполняет указанное SQL утверждение, которое может вернуть несколько результатов. В некоторых (необычных) ситуациях один оператор SQL может возвращать несколько результирующих наборов и / или счетчиков обновлений. Обычно вы можете игнорировать это, если вы (1) не выполняете хранимую процедуру, которая, как вы знаете, может вернуть несколько результатов, или (2) вы динамически выполняете неизвестную строку SQL. Метод execute выполняет оператор SQL и указывает форму первого результата. Затем вы должны использовать методы getResultSet или getUpdateCount для получения результата и getMoreResults для перехода к любому последующему результату (ам).

Примечание: Этот метод нельзя вызывать для PreparedStatement или CallableStatement .

Параметры:
sql - любой оператор SQL
Возвращает:
true, если первый результат является объектом ResultSet ; false, если это счетчик обновлений или нет результатов

Это означает, что Statement.execute() вернет true , если результат равен ResultSet - и это так даже если в базе данных нет записи для оператора SELECT. В этом случае ResultSet будет просто пустым, но все равно будет ResultSet.

Это также означает, что вы должны изменить свой код (если вы хотите придерживаться первого вызова Boolean ret = st.execute(sql);) вот так:

…
if( ret )
{
    ResultSet rs = st.getResultSet();
    String name = null;
    …
}

Таким образом вы избегаете второго обхода базы данных для выполнения Statement.executeQuery().

Или делаете это так:

var url = "jdbc:mysql://localhost/records";
var sql = "SELECT * FROM patient_info WHERE name = '" + txt1.getText() + "'";
var found = false;
try( var con = DriverManager.getConnection( url, "root", "" );
     var st = con.createStatement();
     var rs = st.executeQuery( sql ) )
{
    while( rs.next() ) 
    {
        var name = rs.getString( "name" );
        txt2.setText( name );
        System.out.println( "working" ); 
        found = true;
    }
    if( !found )
    {
        txt2.setText( "no records" );
        System.out.println( "no records" );
    }
}
catch( SQLException e )
{
    e.printStackTrace();
}

DriverManager знает драйвер даже без загрузки класса, по крайней мере, если ваш драйвер JDB C был написан после каменного века. А try-with-resources гарантирует, что все должным образом закрыто, когда больше не нужно.

1 голос
/ 26 марта 2020

Вы должны сделать это следующим образом:

ResultSet rs = st.executeQuery(sql);
if (!rs.next()) {
    txt2.setText("no records");
    System.out.println("no records");
}
else {
    do {
        name = rs.getString("name");
        txt2.setText(name);
        System.out.println("working"); 
    } while (rs.next());
}

Кроме того, если в вашем запросе sql есть только одна запись, соответствующая name, все oop не имеет смысла, т.е. это как:

ResultSet rs = st.executeQuery(sql);
if (!rs.next()) {
    txt2.setText("no records");
    System.out.println("no records");
}
else {        
    name = rs.getString("name");
    txt2.setText(name);
    System.out.println("working");        
}

Помимо этого, ниже приведены некоторые важные моменты, которые вы всегда должны учитывать:

  1. Используйте PreparedStatement вместо Statement, чтобы избежать SQL инъекции. Помимо сохранения приложения от атаки SQL, использование PreparedStatement также помогает вам избавиться от заключения строк в одинарные кавычки (как вы это делали в своем запросе sql). Проверьте это для получения дополнительной информации.
  2. Вам не нужно Class.forName("com.mysql.jdbc.Driver"); при использовании DriverManager.getConnection. Проверьте это для получения дополнительной информации.
...