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));
    }
}

上記のコードがfalseを出力するのはなぜですか?

ormliteで許可されているので、コレクションを使用しています。非常によく似たクラスにはtrueを出力する同一のメソッドがあるため、この問題はとにかくormliteが原因である可能性があると思います。

私がやろうとしているのは、によって返されるオブジェクトを変更することです。

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

ただし、そのオブジェクトの変更は保存されません。コレクションに含まれていないので、私は推測しています。

私の解決策は機能しますが、理想的ではありません。

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());
        }
    }
}

私のコードをもっと見る必要がある場合は、質問してください。プロジェクトは多少複雑ですが、sourceforgeでホストされており、必要に応じてリンクを投稿できます。

4

2 に答える 2

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

上記のコードがfalseを出力するのはなぜですか?

一般的な意味では、標準のコレクションを使用して、メソッドにバグがあるかどうかを確認できる唯一のequals()方法です。ほとんどのコレクションでcontains()は、コレクションを繰り返し使用してを使用しますequals()。はObject.equals()機能するので、デフォルトのequalsメソッドをオーバーライドしていて、バグがある可能性があります。

これは、ORMLiteが行うことでもあります。コレクションが熱心な場合は、を使用するアイテムcontains()の内部を呼び出します。コレクションが遅延している場合は、テーブル全体でイテレータを使用し、再び、一致するかどうかを確認するためにを使用します。ArrayListequals()equals()

編集:

あは。メソッドをオーバーライドしていないと述べますequals()

(ORMLiteの観点から)覚えておくべき重要なことの1つは、これは遅延コレクションであり、オブジェクトがメモリに格納されていないことです。レイジーコレクション全体を反復処理しているときはEpisode、データベースからオブジェクトのインスタンスを取得します。次に、を呼び出すと、コレクションを再度contains()繰り返して、データベースから新しいオブジェクトを作成します。2つのオブジェクトを比較しようとしますが、同じオブジェクト参照がないため、使用している場合は同じになることはありません。EpisodeObject.equals()

レイジーコレクションで機能するには、メソッドをオーバーライドする必要があります。equals()contains()

また、投稿はおそらくコードを単純化したものですが、レイジーコレクションを配列にプルして、それを反復処理することを検討してください。配列に対してを実行することはできませんがcontains()、配列を検索する必要がある場合は、データベースを2回繰り返すことはありません。

編集:

そのため、ソリューションはより複雑であることが判明しました。OPにはShow 、熱心なSeasonオブジェクトのコレクションがあり、それぞれが別の熱心なオブジェクトのコレクションを持つオブジェクトがあったことがわかりEpisodeます。デフォルトでは、ORMLiteが熱心なコレクションをネストしている場合は常に、パフォーマンス上の理由から、内側のコレクションが遅延コレクションに変換されます。残念ながら、これはバージョン4.40では十分に文書化されていません。これを変更するには、オブジェクトのコレクションmaxEagerLevel = 2に(またはそれ以上)を設定します。のドキュメントをShow参照してください。maxEagerLevel

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

これで、オブジェクトリレーショナルマッパーであるormliteが、オブジェクトとその変更状態を管理します。また、変更されたエピソードを保存する手段も提供します。あなたの言及したポイントの1つ。ただし、エラーについては、値に基づいて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 に答える