4
private Collection<Episode> episodes = new ArrayList<Episode>();

public void checkEpisodes(String string) {
    for(Episode episode : this.episodes){
        System.out.println(string + this.episodes.contains(episode));
    }
}

Why would the above code print false?

I'm using a collection because that's what ormlite allows. I think the issue may be caused by ormlite anyways, because a very similar class has an identical method that prints true.

What I'm trying to do is modify an object returned by:

public Episode findEpisode(int num) {
    checkEpisodes("Find: ");
    for(Episode episode : this.episodes) {
        if(episode.getNumber()==num) {
            return episode;
        }
    }
    return null;
}

But modification of that object isn't saved. I'm assuming because it's not contained within the Collection.

My solution, which works but isn't ideal:

public void modifyEpisode(Episode episode) {
    checkEpisodes("Modify: ");
    for (Iterator<?> it = this.episodes.iterator(); it.hasNext();) {
        if (((Episode) it.next()).getNumber()==episode.getNumber()) {
            it.remove();
            addEpisode(episode.getNumber(), episode.getLink(), episode.getLinkLabel());
        }
    }
}

If you need to see more of my code, just ask, the project is somewhat involved, but it's hosted on sourceforge and I can post a link to it if necessary.

4

2 回答 2

10
for(Episode episode : this.episodes) {
    System.out.println(string + this.episodes.contains(episode));
}

为什么上面的代码会打印错误?

在一般意义上,使用标准集合是我可以查看您的方法中是否存在错误的唯一equals()方法。对于大多数集合,contains()遍历集合并使用equals(). 这Object.equals()会起作用,因此可能是您已经覆盖了默认equals方法并且其中存在错误。

这也是ORMLite所做的。如果集合是急切的,那么它会调用要使用的项目contains()的内部。如果集合是惰性的,那么它会使用遍历表的迭代器,并再次使用来查看是否匹配。ArrayListequals()equals()

编辑:

啊哈。您声明您没有覆盖该equals()方法。

要记住的一件重要的事情(就 ORMLite 而言)是这是一个惰性集合,内存中没有对象的存储。当您遍历惰性集合时,您会Episode从数据库中获取对象的一个​​实例。然后,当您调用 时contains(),它会再次遍历从数据库创建新Episode对象的集合。它会尝试比较两个对象,但如果您正在使用它们,它们将永远不会相等,Object.equals()因为没有相同的对象引用。

必须重写该equals()方法才能contains()为惰性集合工作。

此外,尽管您的帖子可能是对代码的简化,但您可能会考虑将惰性集合拉入一个数组,然后对其进行迭代。您不能contains()对数组执行 a 操作,但如果您需要搜索数组,则不会在数据库中迭代两次。

编辑:

所以解决方案变得更加复杂。原来,OP 有一个Show 对象,带有急切的对​​象集合Season,每个对象都有另一个急切的Episode对象集合。默认情况下,只要 ORMLite 嵌套了 Eager集合,出于性能原因,内部集合就会变成惰性集合。不幸的是,这在 4.40 版中没有得到很好的记录。您可以通过在对象的集合上设置maxEagerLevel = 2(或更多)来更改此设置。Show请参阅 上的文档maxEagerLevel

@ForeignCollectionField(eager = false, maxEagerLevel = 2)
ForeignCollection<Season> seasons;
于 2012-05-11T16:47:57.970 回答
0

现在,对象关系映射器 ormlite 管理对象及其修改状态。它还提供了保存修改后的情节的方法;您提到的要点之一。但关于错误:您应该根据值创建一个 equals 。在 ORM 和类似的托管库中,您的序列化可能会为您提供同一对象的不同实例/代理,并且对方法的访问可能会被字节码操作 (AOP) 拦截。

修改示例:

for (Order order : account.orders()) {
    // if we are changing some field in the order
    order.setAmount(123);
    // then we need to update it in the database
    account.orders.update(order);
}
于 2012-05-11T17:01:48.007 回答