12

我有这个抽象类:

域项

abstract public class DomainItem {

    @DatabaseField(generatedId = true)
    protected long id;

    @ForeignCollectionField(eager = false)
        protected ForeignCollection<ContentItem> contentItens;

    //getters and setters
}

内容项:

abstract public class ContentItem {

    @DatabaseField(generatedId = true)
    protected long id;

    @DatabaseField(foreign = true)
    protected DomainItem domainItem;


    @DatabaseField()
    protected String content;

    //getters and setters
}

还有这些(没有摘要):

@DatabaseTable()
public class PhytoterapicItem extends DomainItem{

    public PhytoterapicItem(){

    }

}

植物类成分

@DatabaseTable(tableName = "phytoterapiccontent")
public class PhytoterapicContent extends ContentItem {

    @DatabaseField(canBeNull = false)
    private String defaultName;

    @DatabaseField(canBeNull = false)
    private String scientificName;

    //getters and setters
}

在我的 DatabaseHelper 中,我尝试创建表:

//DatabaseHelper
...
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
    try {
        Log.i(TAG, "onCreate");
        TableUtils.createTable(connectionSource, PhytoterapicContent.class);
        Log.i(TAG, "Created table PhytoterapicContent");

        TableUtils.createTable(connectionSource, PhytoterapicItem.class);
        Log.i(TAG, "Created table PhytoterapicItem");
    catch{
       ...
    }

表 PhytoterapicContent 已创建。但我收到以下错误:

java.sql.SQLException:字段“contentItens”列名的外部集合类 br.com.project.model.ContentItem 不包含类 br.com.project.model.PhytoterapicItem 的外部字段

4

2 回答 2

12

我花了一段时间才注意到/理解文档中的这个关键块(http://ormlite.com/docs/foreign-collection):

请记住,当您有一个 ForeignCollection 字段时,集合中的类(在此示例中为 Order)必须具有用于具有该集合的类(在此示例中为 Account)的外部字段。如果 Account 有一个国外的 Orders 集合,那么 Order 必须有一个 Account foreign 字段。它是必需的,以便 ORMLite 可以找到与特定帐户匹配的订单。

我感到困惑的原因是因为我没有找到任何示例代码(在文档或示例项目中),其中“包含的类”引用了带有集合的类。它是口头描述的,但考虑到这种关系的性质 - 对于某些人来说,我认为在最初几次看到它时可能会有点难以理解。

正如上面原始问题中列出的(这就是我最终得到尝试我偶然发现的解决方案的想法),下面的示例块似乎是在 OrmLite 中映射一对多集合关系的正确方法。

此外,还有一个关于集合持有者类需要如何设置到集合元素类中的注释。


以下是需要注意的主要步骤:

A. 在具有集合的类中(在本例中为DomainItem ) ,以这种方式注释集合字段:

@ForeignCollectionField(eager = true)

B. 在集合中包含的类中(在本例中为ContentItem ) ,您必须对包含该集合的父类有一个显式引用:

@DatabaseField(foreign = true) protected DomainItem domainItem;

C. 在持久化 ContentItem 之前,您必须将 DomainItem 保存到该 ContentItem 以便将外键设置回 DomainItem:

curContentItem.setDomainItem(curDomainItem);

contentItemDao.create(curContentItem);`

当我的收藏最初没有被检索到时,我发现了这一点。我查看了表中的 ContentItem,但从未在表中设置 DomainItem_id。

例子:

public class DomainItem {

    @DatabaseField(generatedId = true)
    protected long id;

    @ForeignCollectionField(eager = false)
    protected ForeignCollection<ContentItem> contentItens;

    // ...
}


public class ContentItem {

    @DatabaseField(generatedId = true)
    protected long id;

    @DatabaseField(foreign = true)
    protected DomainItem domainItem;

    public void setDomainItem(DomainItem domainItem) {

       this.domainItem = domainItem;
    }
}
于 2014-04-25T17:35:34.917 回答
11

因此,异常消息旨在提供帮助。要引用它并删除类名:

ContentItem字段列名的外部集合类contentItens不包含类的外部字段PhytoterapicItem

情况似乎如此。无论何时ForeignCollection,集合所包含的类都必须有一个外部字段返回到父类。

在您的情况下,PhytoterapicItem扩展DomainItem具有对象ForeignCollection的类。ContentItem这意味着ContentItem必须有一个外部字段类型PhytoterapicItem。否则,ORMLite将如何知道ContentItem表中的哪些项目与特定的PhytoterapicItem.

外国集合文档中的示例AccountOrder对象可能会对您的架构有所帮助。每个都有一个外来的对象集合。每当您查询一个单独的查询时,都会执行一个查找对应于特定对象的集合。这意味着每个人都必须有一个异物。AccountOrderAccountOrderAccountOrderAccount

于 2012-04-23T20:19:45.950 回答