Grails GORM按CASE语句排序

时间:2015-09-24 18:03:40

标签: grails gorm

我正在尝试使用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列中始终会有结果,但状态特定查询可能没有结果。如果返回了特定状态的答案,我想使用否则一般答案。

1 个答案:

答案 0 :(得分:0)

GORM / Hibernate排序由域/实体属性完成。 GORM不会将属性评估为SQL语句。这是一件好事,因为它很危险。

可能工作的是使用Criteria查询创建SqlProjection:

using UnityEngine;
using System.Collections;

public class MoveArch : MonoBehaviour {
    public Vector3 startPosition;
    public Vector3 endPosition;
    public float resetTime = 1f;
    public float journeyTime = 1f;
    public ArchDirection archDirection;

    public enum ArchDirection {
        Positive,
        Negative
    }

    private float startTime;
    // Use this for initialization
    void Start () {
        startTime = Time.time;
    }

    // Update is called once per frame
    void Update () {
        Vector3 center = (startPosition + endPosition) * 0.1F;
        center -= new Vector3(0, 1, 0);
        Vector3 riseRelCenter = startPosition - center;
        Vector3 setRelCenter = endPosition - center;

        float fracComplete = (Time.time - startTime) / journeyTime;

        transform.localPosition = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete);
        transform.localPosition += center;

        if (Vector2.Distance(transform.localPosition, endPosition) <= 0.1f) {
            Invoke("resetMoon", resetTime);
        }
    }

    void resetMoon(){
        startTime = Time.time;
        transform.localPosition = startPosition;
    }
}

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

在上面的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') } 属性将包含值2或1.这可能不是您想要的,所以您可能会这样做需要替换那些序列引用的表列名称。然后,您需要将hibernate type更改为合适的{{3}}。这意味着两列必须是相同的类型或者是这样的。在SQL术语中,您想要的是一个新的计算字段,其值为sort by。

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

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