JDBC-запрос не возвращает значений без ошибок - PullRequest
0 голосов
/ 20 января 2019

У меня есть локальный SQL-сервер под управлением MariaDB, и мне нужно запрашивать данные из базы данных, используя Java и JDBC.Я могу подключиться к базе данных, а также записать данные, но простой SELECT не работает.

Я уже пытался использовать разные версии mysql-java-connector и проверил, что SQL-сервер обновлен..

Подключение к базе данных:

//Check wether connection already exists
if(connection != null && !connection.isClosed()){
    return;
}
//Create new connection
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/statdb", "root", "");
System.out.println("Connected to Database");
//Update guilds from Database
updateGuildsInDatabase();

Метод, вызываемый в конце, выглядит следующим образом:

private void updateGuildsInDatabase() throws SQLException {
    //Check for not existing connection
    if(connection == null || connection.isClosed()){
        init();
        return;
    }
    ArrayList<String> localInDb = new ArrayList<>();
    Statement qGStmt = connection.createStatement();
    //Execute Query
    ResultSet guilds = qGStmt.executeQuery("SELECT * FROM guilds;");
    guilds.first();
    //Adding results to List
    while(guilds.next()){
        localInDb.add(guilds.getString("guild_uid").toLowerCase());
    }
    System.out.println("Queried: " + localInDb.size());
    this.guildsInDb = localInDb;
}

Таблица "гильдий" в базе данных "statdb"имеет два столбца с именами "guild_uid" (первичный ключ, varchar) и "display_name" (varchar).Я добавил одну запись со значениями "guild_1" и "Test Guild".

Поскольку у меня есть одна запись в таблице 'guilds', я бы ожидал, что консоль будет выглядеть так:

Connected to Database
Queried: 1

Но фактический результат выглядит так:

Connected to Database
Queried: 0

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Сам метод ResultSet#first() перемещает курсор в первую строку набора результатов. Затем метод ResultSet#next() перемещает курсор вперед на единицу и читает любую запись, если она есть.

Следовательно, использование вашего паттерна всегда приведет к пропуску первой записи из набора результатов. Если в результирующем наборе окажется только одна запись, то количество записей будет равно нулю.

Вы, вероятно, должны удалить звонок на ResultSet#first(). Используйте это вместо:

ResultSet guilds = qGStmt.executeQuery("SELECT * FROM guilds;");
while(guilds.next()) {
    localInDb.add(guilds.getString("guild_uid").toLowerCase());
}
System.out.println("Queried: " + localInDb.size());
this.guildsInDb = localInDb;

Причина, по которой вызов ResultSet#next() для нового результирующего набора логически работает, заключается в том, что по умолчанию набор результатов JDBC фактически не начинает указывать на первую запись. Скорее мы обычно продвигаем его к первой записи с самого первого вызова ResultSet#next().

0 голосов
/ 21 января 2019

Два других Ответа верны, вы пропускаете первую строку при получении из набора результатов. Нет необходимости в вашей строке guilds.first();, как они объяснили, результирующий набор автоматически указывает на первую строку по умолчанию.

Пример кода, полученного из ResultSet

Вот полный пример использования H2 Database Engine . Это показывает создание новой базы данных (в памяти, не сохраненной на диске), добавление таблицы, заполнение этой таблицы несколькими строками, а затем извлечение всех этих строк через ResultSet.

Ключевая строка - while ( rs.next() ) {.

package work.basil.example;

import java.sql.*;
import java.util.*;

import org.h2.jdbcx.JdbcDataSource;

import javax.sql.DataSource;

public class GuildDemo {

    public static void main ( String[] args ) {
        GuildDemo app = new GuildDemo();
        app.doIt();
    }

    private void doIt ( ) {

        DataSource dataSource = null;
        final String catalogName = "guild_demo_";
        final String tableName = "guild_";

        // Verify JDBC driver.
        try {
            Class.forName( "org.h2.Driver" );
            JdbcDataSource ds = new JdbcDataSource(); // The `javax.sql.DataSource` interface implemented by `org.h2.jdbcx.JdbcDataSource`.
            ds.setURL( "jdbc:h2:mem:" + catalogName + ";DB_CLOSE_DELAY=-1" );  // Set delay to -1 to keep in-memory database even after last connection closed.
            ds.setUser( "scott" );
            ds.setPassword( "tiger" );
            ds.setDescription( "Dummy database for demo showing how to retrieve rows from a ResultSet." );
            dataSource = ds;  // Generalize from the concrete class to the interface.
        } catch ( ClassNotFoundException e ) {
            e.printStackTrace();
            return;
        }

        // Connect, and create database.
        try (
                Connection conn = dataSource.getConnection() ;
        ) {
            String sql = null;

            // Create table.
            try ( Statement stmt = conn.createStatement() ; ) {
                sql = "CREATE TABLE " + "guild_" + " ( \n" +
                        " pkey_ UUID DEFAULT random_uuid() PRIMARY KEY , \n" +
                        " name_ VARCHAR NOT NULL \n" +
                        ") ; \n";
                System.out.println( "TRACE - SQL:\n" + sql );
                stmt.execute( sql );
            }

            // Add rows.
            sql = "INSERT INTO guild_ ( name_ ) \n" +
                    "VALUES ( ? ) " +
                    "; ";

            List < String > names = List.of( "Alpha" , "Beta" , "Gamma" , "Delta" ); // Insert a row for each of these names.
            System.out.println( "Inserting list of names: " + names );
            try (
                    PreparedStatement ps = conn.prepareStatement( sql ) ;
            ) {
                for ( String name : names ) {
                    ps.setString( 1 , name );
                    ps.executeUpdate();
                }
            }

            // Retrieve rows from a `ResultSet`.
            sql = "SELECT * FROM " + "guild_" + " ;";
            try (
                    Statement stmt = conn.createStatement() ;
                    ResultSet rs = stmt.executeQuery( sql ) ;
            ) {
                while ( rs.next() ) {
                    UUID pkey = rs.getObject( "pkey_" , UUID.class );
                    String name = rs.getString( "name_" );
                    System.out.println( "Row pkey_: " + pkey + " name_: " + name );
                }
            }


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

}

При запуске.

Вставка списка имен: [Альфа, Бета, Гамма, Дельта]

Строка pkey_: 69908390-5fa6-4eee-8e12-40106db8d60d name_: Alpha

Строка pkey_: 3116acb9-fcce-427f-b222-99c78c6e752a name_: Beta

Строка pkey_: b3fd0930-a2e7-461a-be70-f05124fc58de name_: Gamma

Строка pkey_: dddb423a-5eb2-4e5e-be16-7bb0c27c0033 name_: Delta

0 голосов
/ 20 января 2019

Не думаю, что вам нужно guilds.first().Попробуйте удалить его.

В соответствии с ResultSet JavaDoc:

A ResultSet курсор изначально расположен перед первой строкой;первый вызов метода next делает первую строку текущей строкой;второй вызов делает вторую строку текущей строкой и т. д.

Я считаю, что то, что здесь происходит, guilds.first() устанавливает курсор с before первой строки на первую строку.И guilds.next() в цикле while переместите курсор на один шаг вперед.Следовательно, вам не хватает первого ряда.

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