0

GORM キャッシングを扱っていると思われる奇妙な動作が見られますが、問題を解決する方法がわかりません。それぞれ開始日を持つ purchaseOrderEntries のリストを持つプロジェクト オブジェクトがあります。ユーザーが発注書の州の日付に 2 桁の年を入力した場合、それを 4 桁の年に変換してから、日付を並べ替えます。しかし、それらは正しくソートされていません! 重要なスニペットは次のとおりです。

def updatePurchaseOrderEntryDates(def project) {
   def poEntryList = project.purchaseOrderEntries
   poEntryList?.each { DateHelper.updateTwoDigitYear(it?.startDate) }  // 2-digit yr

   poEntryList?.sort()
   log.info "list 1: " + poEntryList
   poEntryList?.sort()
   log.info "list 2: " + poEntryList

次を出力します。

list 1: 1965, 2020, null
list 2: 2020, 1965, null

同じ並べ替えメソッドを呼び出すと、2 回目に異なる結果が得られるのはなぜですか? 私は何が欠けていますか?これは、休止状態の遅延ロードまたはキャッシングまたは何かの問題のように感じます。全く分からない。何か案は?

* より多くの情報で更新 * すべてのアイデアをありがとう。残念ながら、解決策はそれほど簡単ではないようです。並べ替えは正しく機能しています。毎回機能しているように見えます。これが、私があまり知らない何かの問題のように思われる理由です。プロジェクト オブジェクトには、購入注文エントリのリストが含まれます。これはリスト (セットではない) であり、 PurchaseOrderEntry オブジェクトは Comparable を実装します。コードは次のとおりです。

class Project ... {

    static hasMany = [purchaseOrderEntries:ProjectPurchaseOrderEntry, ...]

    static mapping = {
        purchaseOrderEntries cascade:'all-delete-orphan'
        ...
    }

    List<ProjectPurchaseOrderEntry> purchaseOrderEntries
    ...
}


class ProjectPurchaseOrderEntry ... implements Comparable {

    Project project
    Date startDate
    Date endDate

    ...

    int compareTo(obj) {
        // Compare these dates in reverse older. i.e. put the newest/earliest date on the top and the oldest/null date at the end of the list
        return obj.startDate <=> startDate     // this comparison is done in reverse - comparator operator is null safe
    }

    ... 

}

つまり、ソートはうまく機能しているように見えます。問題はこちら

  poEntryList?.each { DateHelper.updateTwoDigitYear(it?.startDate) }  // 2-digit yr   
  poEntryList?.sort()

リスト内のすべての日付が 4 桁の年に更新されても、それらの日付が更新されていないかのように並べ替えられます。2 桁の年はユリウス暦の日付であり、4 桁の年はグレゴリオ暦の日付であり、比較演算子は黙って失敗していると思われます。しかし....前の各ループにあったので、日付がまだ更新されていないのはなぜですか? それは私が得ていないものです。それぞれが project.purchaseOrderEntries を遅延フェッチするために SQL クエリを実行してから、(新しくソートされたリストの代わりに) これを再度使用していますか? 次のような新しいリストに並べ替えの結果を保持していても、

    poEntryList?.each { DateHelper.updateTwoDigitYear(it?.startDate) }  // support two digit year entry
    def sortedList = poEntryList?.sort({it?.startDate})?.reverse()

新しい「sortedList」はまだ正しくソートされていません。これを可能な限り見る唯一の方法は、ソートに更新された日付を使用していない場合です。繰り返しになりますが、ご協力いただきありがとうございます。どんなアイデアでも大歓迎です。これは私を夢中にさせています。

4

4 に答える 4

1

デフォルトでは、Hibernate はソート順を提供しません。だから私はそれがうまくいくと仮定し、あなたの sort() メソッドは何もしません。次のように、並べ替え順序を指定する必要があります。

def sortedList = poEntryList?.sort { it.startDate }
于 2012-12-04T10:43:01.267 に答える
0

Groovy-JDKCollection.sort()メソッドは、呼び出されたコレクションがである場合にのみインプレースでソートしListます。hasManyリレーションはSetデフォルトであるため

poEntryList.sort()

変更せずに、新しいpoEntryListものをソートされた順序で返します(ここで「ソートされた」とは、コレクション内のオブジェクトの順序に従うことを意味します)。元のコレクションではなく、返されたコレクションをログに記録した場合は、一貫してソートされた順序で表示されるはずです(もちろん、オブジェクトに意味のあるメソッドがあると仮定します)。 ListcompareToListsort()compareTo

于 2012-12-04T22:50:15.187 に答える
0

hasManyGrailsの関係は、データ型を使用しSetます。セットには設計による順序がないため、何を注文するかを指定しないと、何も実行されません。

投稿を更新した後に更新します。

1)List<ProjectPurchaseOrderEntry> purchaseOrderEntriesに簡略化できますList purchaseOrderEntries

2)A.each{ .. }はコレクションを返しません。それは単なるループです。.collect{..}配列内のアイテムをクロージャー内のコードで更新する場合に必要です。

3)hasManyタイプのAは、ListComparableを実装することを意図していないため、オーバーライドは必要ありません。要素がリストに追加された順序で並べ替えられます。

4)一度実行する.collect{ .. }と、ドメインオブジェクトのリストがなくなるため、設定した並べ替えは使用されません。私の意見は、標準のSetデータ型を使用してから収集を行い、次のように言うことです。.sort{it.startDate}.reverse()

于 2012-12-04T22:06:23.900 に答える
0

この問題は何度か私を悩ませてきました。戻り値の型を確認してください - おそらく Set です。ArrayList に変換してからソートする必要があります。次のことを試してください。

def sortedList = poEntryList?.toArray().sort { it.startDate } 
于 2015-07-29T20:47:20.577 に答える