【问题标题】:Android OrmLite Foreign Key / Foreign CollectionAndroid OrmLite 外键/外集合
【发布时间】:2017-03-31 18:13:22
【问题描述】:

在我最近的 Android 项目中,我使用 OrmLite 对一对多关系以及简单的一对一关系进行建模。 我注意到,在一对多关系中,子节点在数据库中持有对父节点的外键引用。仍然在加载父对象时,OrmLite 知道要做什么并加载子元素的集合,这当然是所需的行为。

但是,对于简单的一对一关系,似乎需要父对象持有外键列才能实现相同的行为。

所以实际的问题是:当仅在子对象中设置外键时,是否可以让 OrmLite 以一对一的关系加载子对象,因为这是具有一对多关系的标准行为?

下面是一些示例代码:

@DatabaseTable
public class Parent
{  

@DatabaseField(foreign = true)
private Child1 child1;

@ForeignCollectionField
private Collection<Child2> children2;

}

所以在孩子 1 和 2 中,我需要像这样引用父级:

 public class Child1 / Child2
{       

    @DatabaseField(foreign = true)
    private Parent parent;
}

所以在保存 child2 时,我只需设置

child2.setParent(parent);
child2Dao.create(child2)

但是为了在查询包括 child1 和 child2 在内的父级时达到相同的行为,我必须以相反的方式保存关系:

parent.setChild1(child1)
parentDao.create(parent)

这非常不方便,因为我希望 child1/child2 都持有父级的外键或相反。但是混合起来似乎有些难看!

有什么想法可以实现吗?

我已在此处搜索该问题的答案,但找不到。如果是重复的,对不起!

非常感谢!

编辑:

更准确地说: 是否可以在我的 child1 表中设置外键,并且在查询 Parent 时仍然能够获取 child1。 ORMLite 会自动为 child2 的外部集合执行此操作。我希望 child1 具有相同的行为。 但是当我设置

child1.setParent(parent);
child1Dao.create(child1);

然后进行查询

Parent parent = parentDao.queryForId(1)

只获得 child2,因为父表没有对 child1 的引用(外键)。只有 child1 有对父级的引用。

所以:我想要么让 OrmLite 自动更新父外键列,要么告诉 Ormlite 仍然获取 child1,即使在父级中没有设置外键(这正是 child2 集合的情况)。 这有可能吗?还是不行?

我希望这不会太混乱 :) 我完全知道在父级中设置外键会更简单。但我真的不喜欢这种方法,因为我最终会得到一些孩子拥有父母的外键,而另一些则没有。

非常感谢

【问题讨论】:

    标签: java android ormlite foreign-collection


    【解决方案1】:

    ORMLite 支持“外来”对象的概念,其中一个或多个对应于一个对象的字段被持久保存在同一数据库的另一个表中。例如,如果您的数据库中有一个 Order 对象,并且每个 Order 都有一个对应的 Account 对象,那么 Order 对象将具有外部 Account 字段。对于外来对象,只有来自 Account 的 id 字段作为“account_id”列持久保存到 Order 表中。例如,Order 类可能类似于:

    @DatabaseTable(tableName = "orders")
    public class Order {
    
        @DatabaseField(generatedId = true)
        private int id;
    
        @DatabaseField(canBeNull = false, foreign = true)
        private Account account;
        …
    }
    

    Order 表创建后,会生成如下 SQL:

    CREATE TABLE `orders`
       (`id` INTEGER AUTO_INCREMENT , `account_id` INTEGER,
        PRIMARY KEY (`id`)); 
    

    当您使用外来对象创建字段时,请注意不会自动为您创建外来对象。如果您的外部对象有一个由数据库提供的生成 ID,那么您需要在创建任何引用它的对象之前创建它。例如:

    Account account = new Account("Jim Coakley");
    accountDao.create(account);
    // this will create the account object and set any generated ids
    
    // now we can set the account on the order and create it
    Order order = new Order("Jim Sanders", 12.34);
    order.setAccount(account);
    …
    orderDao.create(order);
    

    外部集合允许您在帐户表中添加订单集合。每当查询返回 Account 对象或由 DAO 刷新时,都会对订单表进行单独的查询,并在帐户上设置订单集合。集合中的所有订单都有一个与帐户匹配的对应外来对象。例如:

    public class Account {
        …
        @ForeignCollectionField(eager = false)
        ForeignCollection<Order> orders;
        …
    }
    

    在上面的示例中,@ForeignCollectionField 注释标记了 orders 字段是与帐户匹配的订单的集合。订单的字段类型必须是 ForeignCollection 或 Collection——不支持其他集合,因为它们要重得多,支持的方法很多。

    来源:http://ormlite.com/

    【讨论】:

    • 非常感谢您的快速响应!我完全了解 ORM 的基本功能,因为我来自 MS 实体框架背景。看来我的问题不是很清楚,我会尝试更新。
    • 所以请看一下编辑。我实际上可能需要像@ForeignField(我假设在OrmLite中不存在)这样的东西,它不存储外键但告诉ORMLite在查询帐户(父)时包含订单(子)
    【解决方案2】:

    根据ORMLite documentation,默认情况下,DatabaseField 的 canBeNull = true。因此,创建 Child1 时无需设置 Parent。要获取 Parent 中的 Childs,反之亦然,可以设置 foreignAutoRefresh = true。

    如果您只想将外键列保留在一个表中,也许您可​​以通过设置 maxForeignAutoRefreshLevel = 1 来实现。

    【讨论】:

    • 感谢您的回复!不幸的是,这不是我想要的。我知道foreignAutorefresh,但我的问题指向另一个方向。我会更新我的问题。
    • 我理解你的问题。我在 ORMLite 文档中也没有找到答案,您可以尝试将您的问题发送给 ORMLite 开发团队。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多