Каковы лучшие практики для обработки чтения / записи пользовательских данных в SQLite? - PullRequest
0 голосов
/ 03 февраля 2019

Я разработчик для сервера в Minecraft, мы недавно открыли и испытали сбои сервера (проблема с хостом), эти сбои включали потерю данных (в нашем основном плагине) от многих игроков, потому что это сохраняло бы только когда они регистрируютсявыкл.Я подумал о решении, но когда в чате написано более 2 сообщений, он выдает исключение SQL, сообщающее, что база данных закрыта.Мы используем SQLite.

Старый метод сохранения при выходе из системы.

что я бы сделал для каждого игрока при входе в систему, чтобы выбрать все столбцы из таблицы «Игроки» ипоместите всю информацию в HashMap, так как сервер работал, я получал / помещал данные в HashMap, и когда игрок выходит из системы / сервер закрывался, он брал HashMap и помещал его обратно в наш файл SQLite.

код из SQLite в HashMap

private void playerRecordToMap() throws SQLException
{
    List<String> columnNames = getDB().queryColumnName(Statements.SELECT("Players", pUUID));

    for (String column : columnNames)
    {
        if (!column.equals("UUID"))
        {
            System.out.println(column);
            Object obj = getDB().queryValue(Statements.SELECT_COLUMN("Players", column, pUUID), column);
            if (obj != null)
            {
                playerRecord.put(column, obj);
            }

        }

    }
}

HashMap в SQLite

public void mapToPlayerRecord()
{
    for (String s : playerRecord.keySet())
    {
        System.out.println(s);
        getDB().executeStatement(Statements.UPDATE("Players", s, playerRecord.get(s).toString(), pUUID));
    }
}

например, получение значения с использованием старого способа.

public Rank getRank()
{
    int rankId = (int) playerRecord.get("RANK");
    return Rank.fromId(rankId);
}

Поскольку сервер несколько раз падалВременами, и это могло произойти в будущем, я понял, что для предотвращения потери данных я должен напрямую общаться с файлом SQLite, но это, конечно, приводит к SQLException, что база данных закрыта.

Новый метод сохранения

public Rank getRank()
{
    String GET_RANK = Statements.SELECT("Players", pUUID);
    int rankId = (int) getDB().queryValue(GET_RANK, "RANK");
    return Rank.fromId(rankId);
}

public void setRank(int id)
{
    String UPDATE_RANK = Statements.UPDATE("Players", "RANK", String.valueOf(id), pUUID);
    getDB().executeStatement(UPDATE_RANK);
}

Я проверил все методы операторов в своем классе «Утверждения», и у них нет проблем, поскольку они работали по-старому.

Как только игрок пишет более одного сообщения в чате, он выдает это исключение (поскольку каждое сообщение чата требует ранг игрока и некоторую другую информацию, которую плагин извлекает прямо из файла SQLite).

значение запроса и методы выполнения операторов

public Boolean executeStatement(String statement)
{
    Connection conn = null;
    PreparedStatement ps = null;
    try
    {
        conn = getConnection();
        ps = conn.prepareStatement(statement);
        return !ps.execute();
    } catch (SQLException ex)
    {
        getLogger().log(Level.SEVERE, "can't execute", ex);
        return false;
    } finally
    {
        try
        {
            if (ps != null)
                ps.close();
            if (conn != null)
                conn.close();
        } catch (SQLException ex)
        {
            getLogger().log(Level.SEVERE, "can't close connection", ex);
            return false;
        }
    }
}

public Object queryValue(String statement, String row)
{
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try
    {
        conn = getConnection();
        ps = conn.prepareStatement(statement);

        rs = ps.executeQuery();
        while (rs.next())
        {
            return rs.getObject(row);
        }
    } catch (SQLException ex)
    {
        getLogger().log(Level.SEVERE, "can't execute", ex);
    } finally
    {
        try
        {
            if (ps != null)
                ps.close();
            if (conn != null)
                conn.close();
        } catch (SQLException ex)
        {
            getLogger().log(Level.SEVERE, "can't close connection", ex);
        }
    }
    return null;
}

Мой вопрос: как лучше всего справиться с ситуацией, описанной выше, и как мне это сделать?

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

журнал ошибок в pastebin

Редактировать 2: ошибка в редактировании 1, кажется, вызвана SQLite, так что это возвращает нас к решению вопроса...

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