【问题标题】:Android ORMLite 4.38 allowGeneratedIdInsert causing IllegalStateExceptionAndroid ORMLite 4.38 allowGeneratedIdInsert 导致 IllegalStateException
【发布时间】:2013-02-02 02:33:14
【问题描述】:

我的目标是 Android 2.2 及更高版本。此错误是在运行 4.x 的设备上生成的。我正在使用 ORMLite 4.38 库。

我需要保证每个记录实例对于任意数量的设备都是唯一的。我很高兴看到 ORMLite 支持 UUID 作为 ID。我为我的数据库记录定义创建了一个 UUID - id 抽象基类。 allowGeneratedIdInsert 是完美的解决方案。但此功能似乎会导致“IllegalStateException:无法在 dao 中创建数据元素”。我通过删除此注释进行了测试,没有问题。把它放回去......同样的问题。将基类的东西放在一个记录定义中......同样的问题。

LogCat 还报告:

原因:java.sql.SQLException: Unable to run insert stmt on object - objectid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx

public abstract class UUIDDaoEnabled<T> extends BaseDaoEnabled<T, UUID> {

    //allowGeneratedIdInsert allows us to set UUID when this device db didn't create it
    @DatabaseField(generatedId = true, allowGeneratedIdInsert=true)
    private UUID id;
    ...
    public void setUUIDFromSerializedSource(SerializedModelBinaryInputStream stream, Dao<T, UUID> dao) throws SQLException { //only place we can set UUIDs
        if(id == null)
            dao.refresh((T)this); 

        if(id != null)
            throw new SQLException("Trying to set UUID on existing object");

        id = stream.getCurrentUUID();
    }
    }

我会这样专攻:

@DatabaseTable()
public class Type extends UUIDDaoEnabled<Type> { ... }

我无法从 allowGeneratedIdInsertgeneratedId 的文档中解释这一点。实际上 alloeGeneratedIdInsert 的文档说它覆盖了 generatedId 的默认行为。它还说

仅当数据库支持此行为时才有效

然而,我在其他帖子中读到 ORMLite 4.25 (?) 和更新版本在 Android 设备上支持这种行为。所以,这也不完全正确。或者我正在做一些愚蠢的事情......任何人???

更新:考虑了一分钟后,我意识到allowGeneratedIdInsert 支持和继承都不是根本原因,因为我基于同一个抽象类实例化了其他对象。我无法弄清楚为什么一个特定的班级会导致这个问题。关于违规记录类型的唯一独特之处(与创建的其他类型相比)是一对多中的多,并且包含多对多。这些属性,加上allowGenereatedIdInsert,会是根本问题吗?相反,我应该问,有没有人在这种情况下看到过这个问题?

更新:别管这个问题。我可以使用updateId(...) 代替allowGeneratedIdInsert

【问题讨论】:

  • 听起来您已经解决了这个问题,但我仍然对原因感兴趣。您可以在某处发布 full 异常堆栈跟踪吗?也许pastebin.com
  • @Gray 一个月应该给你足够的时间:pastebin.com/Ebv77KHw
  • @Gray A > B C, A > D C。当 A、B、C 和 D 存在时发生异常,我将 B 的外部集合中的第一个引用添加到 C。
  • @Gray 当我说得如此抽象时,我自己都糊涂了。当我将 C 的外国集合中对 B 的第一个引用添加到 B 记录时......而不是相反。

标签: android ormlite


【解决方案1】:

所以我不确定这一点,但在我看来,您正在尝试将一个元素两次插入到具有相同 UUID id 的表中。例外是说约束失败:

IllegalStateException: Could not create data element in dao
    at BaseForeignCollection.add(BaseForeignCollection.java:57)
...
Caused by: SQLiteConstraintException: error code 19: constraint failed

如果您调用foreignCollection.add(...);,它的作用与dao.create(...); 相同——您不能同时对同一个对象进行这两种操作。如果您有一个已由 DAO 创建的现有对象,并且您希望将其与另一个对象关联,您应该执行以下操作:

   // associate this object with another
   existingObject.setForeignField(...);
   // now update it in the db
   existingObjectDao.update(existingObject);

您不能将其添加到 foreignField 的外部集合中。

【讨论】:

  • 谢谢。我刚刚发现我正在创建多个实例,经过几次日志转储后,我意识到通过设置一对一关系可以自动设置反多对多。根据您的建议,我创建了 B,将 B->C 设置为一,然后将 C->B 设置为多。现在知道了这一点,与 allowGeneratedIdInsert 相关的问题就消失了。相关说明:我讨厌被扔进 RTFM 手册组。我确实看过。我在有关对外关系的文档中找不到任何暗示这种行为的内容。我错过了什么吗?
  • 我在 javadocs 和手册中添加了类似以下的副本: 注意:当您向外部集合添加新对象时,这也会通过调用将其添加到数据库中dao.create(obj)。如果对象已经在数据库中创建,那么您应该在对象上设置外部字段并调用 dao.update(obj)。如果您在此处添加它,DAO 将尝试再次在数据库中创建它,这很可能会导致错误。
  • 您也可以在此处添加相同的注释:ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/…
  • 这个异常只发生在UUID id 使用allowGeneratedIdInsert 时仍然很奇怪。为了澄清您的注释,您可以用“逻辑错误”注释“错误”。
  • 再澄清一点:如果我将一对一关系设置为 null 并更新,是否会从 ForeignCollection 中删除反向关系?你可以在笔记中澄清这一点。
【解决方案2】:

我遇到了类似的问题。但它是由使用 create 而不是 createOrUpdate 来保存对象引起的。

在更改之前卸载应用程序也很重要,以确保数据库已被删除并且不会保留旧行为。

编辑:createOrUpdate 非常耗时。使用大量数据创建更好。

编辑2:也可以使用TransactionManager.callInTransaction

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 2014-11-22
    • 2017-03-15
    • 2021-10-11
    • 2015-04-20
    • 2012-05-09
    相关资源
    最近更新 更多