我正在尝试使用CASE
语句通过GORM查询进行排序。我所拥有的是一列带有state
的 View ,该值可以是状态缩写或单词General
。我将像这样运行查询
Dropdown.findByStateInList(['General','CA'], [sort: "stateOrderBy", order: "asc"]
但返回错误
could not resolve property: stateOrderBy of: workspace.Dropdown
当我像下面这样创建域类时,
stateOrderBy
的值是字符串CASE WHEN state = 'General' THEN 2 ELSE 1 END
而不是1或2,这就是为什么我遇到上述错误的原因。有没有办法评估我的CASE语句?@EqualsAndHashCode(includeFields=true)
class Dropdown implements Serializable {
String state
String dropDownNames
String sectionName
String prefix
Integer displayOrder
def stateOrderBy = "CASE WHEN state = 'General' THEN 2 ELSE 1 END"
static transients = [ "stateOrderBy" ]
static mapping = {
datasource 'plDropdown'
table 'view_AllTables'
id composite: ['state','sectionName','displayOrder']
state column:'state'
dropDownNames column:'DropDownNames'
sectionName column:'SectionName'
prefix column:'Prefix'
displayOrder column:'DisplayOrder'
stateOrderBy column:'stateOrderBy'
version false
}
}
编辑:在
General
列中总会有结果,但是对于特定于状态的查询可能没有结果。如果返回了特定于州的答案,我想使用该答案,否则使用通用答案。
最佳答案
GORM /休眠排序是通过域/实体属性完成的。 GORM不会将属性评估为SQL语句。那是一件好事,因为那很危险。
可以用Criteria查询创建SqlProjection的方法是:
Dropdown.withCriteria {
'in'('state', ['General','CA'])
projections {
property('state')
property('dropDownNames')
property('sectionName')
property('prefix')
property('displayOrder')
sqlProjection "CASE WHEN state = 'General' THEN 2 ELSE 1 END as stateSortBy", 'stateSortBy', org.hibernate.type.IntegerType as org.hibernate.type.Type
}
order('stateSortBy', 'asc')
}
这将动态创建一个将被排序的属性。尽管我认为最好在 View 中做同样的事情。这样,即使使用Dynamic Finder,您也可以按该属性进行排序。
在上面的sqlProjection示例中,即时创建的
stateSortBy
属性将包含值2或1。这可能是您不想要的,因此您需要将这些替换为那些常规引用的表列名称。然后,您需要将hibernate type更改为适当的值。这意味着两列必须为相同类型或强制转换为相同类型。用SQL术语来说,您想要的是一个新的计算字段,该字段具有作为排序依据的值。请注意,由于正在使用投影,结果将是一个包含投影属性(表列)的列表。它不会是一个列表。
关于Domain.executeQuery()和Domain.findAll(sql),它们用于HQL,而不是SQL。
关于grails - Grails GORM按CASE语句排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32768032/