【问题标题】:Grails: Projection on many tables?Grails:在许多表上进行投影?
【发布时间】:2011-08-11 21:55:06
【问题描述】:

我在 Grails 中的投影存在一些问题。您能帮我检查一下并为我提出解决方案吗?

  1. 我想查询许多表上的数据,这些表具有多对一关系并在它们的某些属性上进行投影。例如:

    class Person {
        int id
        String name
        String address
        static hasMany = [cars : Car]
    }
    
    class Car {
       int id
       String brand
       long price
       Person owner
       static belongsTo = [owner : Person]
    }
    

    那么,如何只使用一个查询 withCriteria(应用投影)来获取指定汽车的信息(包括品牌、价格和车主姓名)?是否可以使用:

    Car.withCriteria {
         projections {
             property("brand")
             property("price")
             property("owner.name")
        }
        eq("id", carId)
    }
    
  2. 我可以使用投影来获取一个指定人的信息以及他所有汽车的名称吗?例如:[01, Perter, 01 Street A, [Mercedes, Toyota, Ducatti]]?

  3. 一种特殊情况:(使用上面的 Person 类)
    一个人可以加入许多组织,一个组织可以有一个“父”组织(反之亦然,一个组织可以有许多其他依赖组织)。但是有一条规则:一个人只能加入给定组织的一个子组织。因此,对于给定的组织 O 和个人 P,获取 P 的信息以及以 P 作为成员的 O 的依赖组织的名称的最快方法是什么。我更喜欢使用 Grails 投影。

    这里是数据模型:

    class Person {
        int id
        String name
        String address
        static hasMany = [joinedOrgs : Organization] 
    }
    
    class Organization {
        int id
        String name
        Organization parentOrg
        static hasMany = [members : Person, childOrgs : Organization]
    }
    

我是 Grails 的新手,我想更多地了解 GORM。非常感谢您的帮助。

【问题讨论】:

    标签: grails criteria grails-orm projection


    【解决方案1】:

    对于 (1) 和 (2),我不知道是否有一种方法可以通过 1 个条件查询来完成您想要的操作,但另一种方法似乎更简单自然。对于(1):

    def car = Car.get(carId)
    def owners = car.owner?.name
    

    对于(2)

    def person = Person.get(personId)
    def cars = person.cars*.name
    

    关于 (3),这里有点设计问题。您当前的域设计没有反映您描述的规则,因此很难保持该约束。您可以考虑映射一个 PersonOrganization 表和make childrenOrganization a transient property。例如:

    class Organization {
        int id
        String name
        Organization parent
        static transients = ['children']
        ...
    
        Boolean children() {
            def children = Organization.createCriteria().list() { 
                eq ('parent', this) 
            }
            return children
        }
    }
    

    之后,您可以使用 getAllAncestors() 之类的追溯函数来确定组织的所有父层次结构,并在人员组织列表中查找。这似乎不是最好的方法,但这是一种可能的方法。

    【讨论】:

      【解决方案2】:

      对于(第 1 名)我认为您正在寻找的内容已在此处解释

      http://grails.1312388.n4.nabble.com/grails-reports-page-multiple-domain-criteria-join-td3510604.html

          def criteria = Company.createCriteria() 
          def results =  criteria.list { 
              projections { 
                      property('id', 'company.id') 
                      ... 
                      POCs{ 
                              property('id', 'poc.id') 
                              property('name', 'poc.name') 
                      } 
                      software { 
                              productKey { 
                                      ... 
                                      } 
                      } 
                      ... 
                      order(company.name,'asc') 
              }
      

      使用.createCriteria() 突出显示帖子

      【讨论】:

        【解决方案3】:

        试试这个

        def results =  Car.createCriteria().list() { 
            createAlias('owner','owner')
            projections { 
                property('owner.name', 'owner.name') 
                property('brand','brand')
                property('price','price')
            }
        }
        

        【讨论】:

        • 为什么需要alias
        • @AlexanderSuraphel 没有别名你不能直接在property('owner.name', 'owner.name') 中访问owner.name 即使你可以在没有别名的情况下获得上述结果,但你需要为此编写更多代码。请参阅下面的示例projections { owner { property('name', 'name') } property('brand','brand') property('price','price') } 如果您仍然有任何困惑,请告诉我,或者这不是您的正确答案。谢谢
        • @AlexanderSuraphel 如果您可以在没有createAlias('owner', 'owner') 的情况下编写上面的代码,那么在较新版本的 grails 中可能是可能的
        猜你喜欢
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        • 2014-10-03
        • 2012-04-24
        • 1970-01-01
        • 2013-03-23
        • 2019-09-13
        • 1970-01-01
        相关资源
        最近更新 更多