【问题标题】:Grails GORM sort by CASE statementGrails GORM 按 CASE 语句排序
【发布时间】:2015-09-24 18:03:39
【问题描述】:

我正在尝试使用 CASE 语句按 GORM 查询进行排序。我所拥有的是带有state 列的视图,该值可以是州缩写或单词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 列中总会有结果,但对于特定于州的查询可能没有结果。如果返回了特定于州的答案,我想使用该答案,否则为一般答案。

【问题讨论】:

  • 有必要使用findBy吗?我认为您可以尝试使用 executeQuery:grails.github.io/grails-doc/latest/ref/Domain%20Classes/…
  • 我可以使用它,但它会在很多地方使用,每次编写查询都是不必要的额外工作。
  • 是的。但是您可以在您的域中的静态方法中定义它并在所有地方重用它。

标签: grails grails-orm


【解决方案1】:

GORM/Hibernate 排序由域/实体属性完成。 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')
}

这将动态创建一个按其排序的属性。虽然我认为在视图中做同样的事情会更好。然后,即使使用动态查找器,您也可以按该属性进行排序。

在上面的 sqlProjection 示例中,动态创建的 stateSortBy 属性将包含值 2 或 1。这可能不是您想要的,因此您需要将它们替换为这些序号引用的表列名称到。然后,您需要将hibernate type 更改为合适的值。这意味着两列必须是相同类型或被强制转换。在 SQL 术语中,您需要的是一个新的计算字段,其中包含要排序的值。

请注意,由于正在使用投影,因此结果将是一个包含投影属性(表格列)的列表。它不会是一个列表。

关于 Domain.executeQuery() 和 Domain.findAll(sql),它们是针对 HQL 而不是 SQL。

【讨论】:

猜你喜欢
  • 2015-02-26
  • 2012-05-25
  • 2015-09-26
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
相关资源
最近更新 更多