【问题标题】:GreenDao - Saving an Entity and related - "Entity is detached from DAO context"GreenDao - 保存实体和相关 - “实体与 DAO 上下文分离”
【发布时间】:2018-06-14 18:12:42
【问题描述】:

我正在尝试使用 GreenDAO 保存一个名为 hotel 的实体。每个酒店都有一些协议是一对多的关系,每个协议都有……好吧,一张图片胜过一千字。

现在,我要做的是:

daoSession.runInTx(new Runnable() {
    @Override
    public void run() {

        ArrayList<Hotel> listOfHotels = getData().getAvailability();

            for(Hotel h : listOfHotels)
            {
                List<HotelAgreement> hotelAgreements = h.getAgreements();
                for(HotelAgreement ha : hotelAgreements) {
                    ha.setHotel_id(h.getHotel_id());
                    HotelAgreementDeadline hotelAgreementDeadline = ha.getDeadline();
                    List<HotelRemark> hr = hotelAgreementDeadline.getRemarks();
                    List<HotelAgreementDeadlinePolicies> hadp = hotelAgreementDeadline.getPolicies();

                    daoSession.getHotelReportDao().insertOrReplaceInTx( h.getReports() );
                    daoSession.getHotelPictureDao().insertOrReplaceInTx( h.getPictures() );

                    daoSession.getHotelRemarkDao().insertOrReplaceInTx(hr);
                    daoSession.getHotelAgreementDeadlinePoliciesDao().insertOrReplaceInTx(hadp);
                    daoSession.getHotelAgreementDeadlineDao().insertOrReplace(hotelAgreementDeadline);
                    daoSession.getHotelAgreementDao().insertOrReplace(ha);
                }

                //                daoSession.getHotelReportsDao().insertOrReplace( getData().getReports() );

            }

        daoSession.getHotelDao().insertOrReplaceInTx(listOfHotels);
    }
});

这当然行不通。我在以下行收到“实体与 DAO 上下文分离”错误:

HotelAgreementDeadline hotelAgreementDeadline = ha.getDeadline();

我理解这是因为我尝试从不是来自数据库的酒店实体获取协议,而是从另一个来源(在本例中为 Web 服务)获取协议。但是为什么 ha.getDeadline() 会发生这种情况,而不是 h.getAgreements()?

现在,我有了 Hotel 对象,它包含几乎所有数据:协议、截止日期、政策、备注、图片、报告。我只想告诉GreenDAO:保存它!如果我不能,我必须循环遍历树——这就是我试图用上面的代码做的——我应该怎么做?

Here 我读到我必须“首先使用 Dao 存储/加载对象”。非常棒,但是......它是如何工作的?我阅读了greenDAO documentation about relations,但找不到任何东西。

感谢所有愿意提供帮助的人 :-)

【问题讨论】:

  • 不知道什么很难说 getData().getAvailability();做。此外,这将有助于了解您如何生成实体以及您拥有哪些实体。
  • 我从 web 服务获得响应并将其转换为:responseAgreements = (HotelAvailabilityResponse) response;。这是我调用 getAvailability 的对象,只是返回一个 Hotel 对象列表。这些来自网络服务的响应,从未见过数据库,我可以将它们存储到数据库中,但不存储子项目。如果我尝试检索它们 - 就像它因 Entity is detached from DAO context 错误而中断。关于关系,您想确切了解什么?我可以发布我的 GreenDaoGenerator 片段
  • 当应用程序加载时,我对早餐类型做同样的事情。我打电话给daoSession.getHotelBreakfastDao().insertOrReplaceInTx(getData().getBreakfasts());,我从getData().getBreakfasts() 得到的是一份HotelBreakfast 列表。但是它们与其他表没有任何关系,因此可以完美地插入数据库。
  • 我认为如果您通过getData().getAvailability();中的代码会有所帮助

标签: java android orm greendao


【解决方案1】:

在某些时候,当您从 web 服务获得响应时,您正在创建新的实体对象并用信息填充它们。之后尝试在数据库中插入每个新对象。

如果需要,您可以使用 insertOrReplaceInTx 插入例如酒店的所有 n 协议,但在所有涉及的对象都在数据库中之前,您不应该使用任何关系。

【讨论】:

  • 我相信这就是我已经在做的事情了:-/ 如果我评论中间的所有行,我只是做ArrayList&lt;Hotel&gt; listOfHotels = getData().getAvailability(); daoSession.getHotelDao().insertOrReplaceInTx(listOfHotels); 它可以工作,我将所有酒店保存在数据库中(但只是酒店)。为什么它不适用于其他实体?
  • List&lt;HotelAgreement&gt; hotelAgreements = h.getAgreements(); 这样的行,当酒店或他们的协议都没有存储在数据库中时,您正在使用酒店和协议之间的关系。
  • 好的,我现在看到了问题:由于这两个实体不在数据库中,我无法从酒店获得协议,即使酒店已经获得了所有数据。但是,既然我得到了一个完整的 Hotel 对象,以及它的所有子对象,我应该如何将它存储到数据库中?我是不是把所有的 ORM 理论都弄错了?我应该尝试什么方法?谢谢。
  • 您主要从您的网络服务获得什么?也许是一个 JSON?还是你得到了整个 Hotel 对象?
  • 我得到一个 JSON。 Jofre,我们是否应该在chat.stackoverflow.com/rooms/71661/android-discussions 聊天中见面?如果你愿意,我已经在那里了。
【解决方案2】:

我认为greendao团队必须在方法中添加以下控件 getToOneField() 就像在 getToManyList() 中一样

if(property == null){
    code already generated by greendao plugin
}
return property;

在您的情况下,在 HotelAgreements 类中

@Keep
public DeadLine getDeadLine {
    if(deadLine == null) {
        long __key = this.deadLineId;
        if (deadLine__resolvedKey == null || !deadLine__resolvedKey.equals(__key)) {
            final DaoSession daoSession = this.daoSession;
            if (daoSession == null) {
                throw new DaoException("Entity is detached from DAO context");
            }
            DeadLineDao targetDao = daoSession.getDeadLineDao();
            DeadLine deadLineNew = targetDao.load(__key);
            synchronized (this) {
                deadLine = deadLineNew;
                deadLine__resolvedKey = __key;
            }
        }
    }
    return deadLine;
}

添加控件

if(deadLine == null) {
    ...
}

所以如果你从 rest json 接收数据 对象被填充并且 getProperty() 方法从对象而不是从数据库返回属性字段,就像它对列表所做的那样 然后你可以插入或替换它

然后,当您从 db 加载或深度加载对象时,该属性为 null,greendao 从 DB 获取它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    相关资源
    最近更新 更多