在SQLite中处理读取/写入用户数据的最佳做法是什么?

时间:2019-02-03 07:20:02

标签: java sqlite

我是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);
}

我已经检查了“ Statements”类中的所有语句方法,由于它们使用的是旧方法,因此它们没有问题。

只要玩家在聊天中写入多个消息,就会引发该异常(因为每条聊天消息都需要玩家的等级以及插件直接从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;
}

我的问题是: 解决上述情况的最佳方法是什么?如何做?

编辑: 奇怪的是,我已经在测试服务器上进行了多次测试,并且崩溃了,并且主机显示的错误非常相似,甚至是相同的错误,但是看起来却不像插件错误。

error log in pastebin

编辑2: 编辑1中的错误似乎是由SQLite引起的,因此使我们回到问题的解决方案是什么...

0 个答案:

没有答案