【问题标题】:LinkedList like database ORM liteLinkedList 类似于数据库 ORM lite
【发布时间】:2015-02-04 13:54:09
【问题描述】:

我正在尝试创建(如果可能的话)类似 LinkedList 的数据库。

我的想法是,我添加到表中的数据需要具有复杂的订单结构,因为当我添加新项目时,我可以将其添加到列表中的任何位置。

例如,如果我有一个包含项目 (1)、(2)、(3)、(4)、(5) 的列表。我可以直接在位置 (2) 上添加一个新项目,从而改变整个列表(或至少在位置 (2) 上的项目之后的元素)。

为此我必须考虑的另一件事是每个项目都必须知道他以前的项目的 ID(不是索引,而是从服务器获取的一些自定义 ID)。当我还必须在服务器上重新订购列表时,实际上将需要此 ID(当我上传项目时,还必须发送具有先前 ID 的订购请求)。

此时,我的文档模型如下所示:

@DatabaseTable(tableName = DocumentsTable.TABLE_NAME, daoClass = DocumentDao.class)
public class Document implements Parcelable {    
@DatabaseField(columnName = DocumentsTable.LOCAL_ID_COLUMN, generatedId = true, dataType = DataType.INTEGER)
    int localId;
    @DatabaseField(columnName = DocumentsTable.SERVER_ID_COLUMN, unique = true, dataType = DataType.STRING, useGetSet = true)
    String serverId;
    @DatabaseField(columnName = DocumentsTable.ALIAS_COLUMN, dataType = DataType.STRING, useGetSet = true)
    String alias;
    @DatabaseField(columnName = DocumentsTable.NAME_COLUMN, dataType = DataType.STRING, useGetSet = true)
    String name;
    @DatabaseField(columnName = DocumentsTable.DESCRIPTION_COLUMN, dataType = DataType.STRING, useGetSet = true)
    String description;
    @DatabaseField(columnName = DocumentsTable.OWNER_COLUMN, dataType = DataType.STRING, useGetSet = true)
    String owner;
...

我在想的是添加两个新列,我们称它为 prevDocnextDoc 并将它们设置为 Foreig 键。像这样的:

@DatabaseField(columnName = DocumentsTable.PREVIOUS_DOC, foreign = true, canBeNull = true)
    Document prevDoc;
@DatabaseField(columnName = DocumentsTable.NEXT_DOC, foreign = true, canBeNull = true)
    Document nextDoc;

这样,我表中的每个项目都将知道它的上一个项目应该是什么以及下一个项目应该是什么。

但是

现在我被卡住了,在这一点上,我不知道如何才能以正确的顺序对其进行排序。另外,如何正确添加新项目?

新想法?

在这一点上,我认为我走错了路,似乎找不到好的解决方案。我在 ORMLite 文档中进行了搜索,但没有发现任何可以帮助我的东西。像数据库这样的基本链表的例子也没有帮助我。我找到了一些图形数据库,但我无法在 Android 中使用它们,而且它们对于我需要的东西来说太过分了。

最后机会 作为最终解决方案,我添加了一个新列 orderPos,我手动更新了该列:

@DatabaseField(columnName = DocumentsTable.ORDER_POS, dataType = DataType.INTEGER, useGetSet = true)
int orderPos;

这是这样使用的: 对于每个项目,我设置了一个 orderPos 值,该值在每个步骤中递增。 当我需要将一个项目添加到特定位置时,我会获取该项目之后的所有项目并将它们的 orderPos 增加 1,然后我将项目添加到我想要的位置的 orderPos 中。 我知道这将涉及 O(n-pos) + 1 的复杂度,但我暂时想不出其他任何东西。

请让我知道您的想法以及如何使用 ORMLite 在 Android 上正确实现类似的功能。

【问题讨论】:

    标签: java android linked-list ormlite


    【解决方案1】:

    这样,我表中的每个项目都将知道它的上一个项目应该是什么以及下一个项目应该是什么。

    是的,这有点奇怪。通常,字段将确定顺序,并且由于您正在存储字段,因此您只需使用 qb.orderBy(...) 方法以任何顺序输出列表。

    例如,如果我有一个包含项目 (1)、(2)、(3)、(4)、(5) 的列表。我可以直接在位置 (2) 上添加一个新项目,从而改变整个列表(或至少在位置 (2) 上的项目之后的元素)。

    所以我假设您将一个项目插入位置 2,但是如果您在位置 2 插入另一个项目,则前一个 #2 项目将变为 #3。是的,这很难。

    对于每个项目,我设置了一个 orderPos 值,该值在每个步骤中递增。当我需要将一个项目添加到特定位置时,我会获取该项目之后的所有项目并将它们的 orderPos 增加 1,然后我将项目添加到我想要的位置的 orderPos 中。我知道这将涉及 O(n-pos) + 1 的复杂度,

    是的。这听起来很对。您可以在 1 个 SQL 表达式中进行更新,因此每次插入都需要 2 个 SQL 操作。除非您的表中有很多行,否则这不会太痛苦。

    跳出框框思考,您可以做的一件事是使用Long 值的宽度。列表中的第一项获得Long.MAX_VALUE / 2。每当您插入到列表中时,您都会获取左侧排序值和右侧排序值并取它们的平均值。您必须在要插入的值的任一侧找到这两个值,这需要 2 次查询,但您不需要更新所有行。

    1. 查找行>= 我正在插入的行。如果没有,那么Long.MAX_VALUE
    2. 找到我要插入的行<。如果没有,则为 0。
    3. 平均每一行的顺序列。
    4. 插入新行。

    但我认为你的职位想法可能更适合你的情况。

    【讨论】:

    • 谢谢你的回答,最后我决定用别的东西。我使用带有浮点值的 orderPos 并将其设置为每个项目。当我需要通过将项目添加到另一个位置来重新排序时,我从该值中减去 0,000001 并将其设置为新项目。当值相同时,我用那个值和之前的值做一个中位数。这样我就不必重新排序整个列表!
    • 酷@IonutNegru。是的,这与我使用 long 的想法相似。小心浮点空间中的舍入误差。
    猜你喜欢
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    相关资源
    最近更新 更多