我看到一些我认为处理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”仍未正确排序。我认为这是可能的唯一方法是它没有使用更新的日期进行排序。再次感谢您的帮助。欢迎任何想法。这个让我发疯。
答案 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 }