使用 withCriteria 时限制数据范围

Posted

技术标签:

【中文标题】使用 withCriteria 时限制数据范围【英文标题】:Restrict the scope of data when using withCriteria 【发布时间】:2013-10-05 15:05:25 【问题描述】:

我目前有以下 3 个域类:

用户.groovy

class User 
    ...

    static hasMany = [
        ...
        ]

    static belongsTo = [        
        course : Course,
        university : University     
        ]


Course.groovy

class Course 

    String title

    static hasMany = [
        universities : University, 
        users : User
        ]

    static belongsTo = University       


University.groovy

class University 

    String name

    static hasMany = [
        courses : Course,
        users : User
        ]           

我使用以下代码收集了一所大学的所有课程:

def courses = Course.withCriteria       
          universities 
            eq('id', Long.parseLong(params.universityId))
          
        
        render courses as JSON  

有一个这样的示例响应:

[
            "class":"classifieds.Course",
            "id":1,
            "title":"Computer Science",
            "universities":
                ["class":"University",
                    "id":1],
            "users":
                ["class":"User"
                    ,"id":1]
        ]

我的问题是我想限制响应的范围不包括当前返回的 usersuniversities,我只需要在 JSON 中返回 courses 的列表。如何限制这个?

【问题讨论】:

University.get( params.long( 'universityId' ) ).courses.title as JSON? 谢谢你 - 关闭.. 是否有可能用id 找回course 以便响应将是"id":1,"title":"Computer Science" 等的集合? University.get( params.long( 'universityId' ) ).courses.collect [ id: it.id, title: it.title ] as JSON? ;-) 不过可能有更有效的方法来获得相同的结果 谢谢 - 它工作。感谢您的帮助 【参考方案1】:

在引导程序中为 Course 注册所需的 JSON 对象编组器,如下所示:

//Bootstrap
def init =  servletContext ->
    JSON.registerObjectMarshaller(Course)
        def returnObj = [:]
        returnObj.id = it.id
        returnObj.title = it.title

        returnObj
    

上述寄存器仅在转换并呈现​​为 JSON 时返回 Course 的字段。请注意,这将永久编组 Course 以仅返回其字段而不是其关联。如果暂时需要,那么您可以很好地遵循 Tim 的方法。

如果你想让它对所有字段都通用,那么:

JSON.registerObjectMarshaller(Course)course ->
    def fields = grailsApplication.domainClasses
                                  .findit.name == 'Course'
                                  .properties
                                  .findAll!it.association
                                  .name - 'version' //Remove version if req.

    return fields.collectEntries[it, course."$it"]

假设grailsApplication被注入到Bootstrap.groovy

补充一点,如果不是为了修改 JSON 的构建方式而是为了协调标准结果,那么使用projections 来获得所需的property

def courses = Course.withCriteria       
   universities 
     eq('id', Long.parseLong(params.universityId))
   
   projections
      property('id')
      property('title')
   

更新: 为了以映射实体的形式检索结果,我将遵循 HQL 作为 shown here 或使用 createCriteria 并将结果转换为如下映射(未经测试):

import org.hibernate.transform.Transformers

def criteria = Course.createCriteria()
criteria.resultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
def courses = criteria.list       
   universities 
     eq('id', Long.parseLong(params.universityId))
   
   projections
      property('id')
      property('title')
   

我不确定属性名称是否会创建别名。如果您遇到任何问题,您可以迅速回退到 HQL 查询。

【讨论】:

我喜欢在尝试时使用projections 的想法,但是根据您上面的内容,响应格式似乎与正常的 JSON 响应不同。它类似于([1:Computer Science],[2:Physics]) 而不是"id":1,"title":"Computer Science","id":2,"title":"Physics" 尝试使用 HQL 或 createCriteria。看我的更新。 @andymccullough

以上是关于使用 withCriteria 时限制数据范围的主要内容,如果未能解决你的问题,请参考以下文章

在假设函数中执行数据库查询时列表索引超出范围

tensorflow 将数值限制在一定范围内

tensorflow 将数值限制在一定范围内

绘图时限制R中的日期范围

Google Maps API V3:限制地图范围[重复]

C - 限制结构范围