Grails排序列表不能产生一致的结果 - 可能是hibernate / gorm缓存问题

时间:2012-12-04 08:27:49

标签: grails gorm

我看到一些我认为处理GORM缓存的奇怪行为,但我不知道如何解决这个问题。我有一个项目对象,其中包含purchaseOrderEntries列表,每个列表都有一个开始日期。如果用户在采购订单状态日期输入两位数年份,我将其转换为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

如何调用相同的排序方法第二次产生不同的结果?我错过了什么?我觉得这是一个hibernate延迟加载或缓存或某些问题。没有线索。有任何想法吗?

*更新W / MORE INFO * 感谢所有的想法。不幸的是,解决方案似乎并不那么容易。排序工作正常,它似乎每次都工作。这就是为什么它似乎是一个我不太了解的问题。项目对象包含采购订单条目列表 - 这是一个列表(不是一组),而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位数年份是公历日期,而我的比较运营商正在默默地失败。但是......为什么日期不会更新,因为它们是在前一个循环中?这就是我没有得到的。是每个做一个SQL查询来延迟获取project.purchaseOrderEntries然后再次使用它(而不是新排序的列表)?即使我在新列表中保存了排序结果,例如:

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

新的“sortedList”仍未正确排序。我认为这是可能的唯一方法是它没有使用更新的日期进行排序。再次感谢您的帮助。欢迎任何想法。这个让我发疯。

4 个答案:

答案 0 :(得分:1)

默认情况下,Hibernate不提供任何排序​​顺序。所以我假设它工作正常,你的sort()方法什么都不做。您应该提供排序顺序,如下所示:

def sortedList = poEntryList?.sort { it.startDate }

答案 1 :(得分:0)

Grails中的hasMany关系使用数据类型Set。一个集合没有设计顺序,所以没有告诉它要点什么,它什么都不做。

更新帖子后更新。

1)List<ProjectPurchaseOrderEntry> purchaseOrderEntries可简化为List purchaseOrderEntries

2).each{ .. }不会返回该集合。它只是一个循环。如果希望数组中的项目由闭包中的代码更新,则需要.collect{..}

3)hasMany类型List并非旨在实现Comparable,因此不需要覆盖。它按元素添加到列表中的顺序排序。

4)执行.collect{ .. }后,您不再拥有域对象列表,因此不会使用您设置的任何排序。我的意见是使用标准的Set数据类型,然后进行收集,然后说出.sort{it.startDate}.reverse()

答案 2 :(得分:0)

Groovy-JDK Collection.sort() method只有在调用它的集合是List时才会就地排序。由于hasMany关系默认为Set

poEntryList.sort()

保持poEntryList不变,并按排序顺序返回 new List(此处“排序”表示根据对象的compareTo排序采集)。如果您记录List而不是原始集合返回的sort(),则应该按照排序顺序一致地看到它(当然假设对象具有有意义的compareTo方法)。

答案 3 :(得分:0)

这个问题多次困扰我。检查返回类型 - 它可能是一个Set。您需要转换为ArrayList然后排序。请尝试以下方法:

def sortedList = poEntryList?.toArray().sort { it.startDate }