Я разработчик для сервера в 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, так что это возвращает нас к решению вопроса...