Граальс: проекция на много таблиц? - PullRequest
8 голосов
/ 24 апреля 2011

У меня есть некоторые проблемы с проекцией в 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]
    }
    

    Итак, как я могу использовать только один запрос с критериями (применить прогноз), чтобы получить информацию об определенном автомобиле (включая марку, цену и имя владельца)? Можно ли использовать:

    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 вместе с именем зависимой организации O, в которой P является членом. Я предпочитаю использовать проекцию Грааля.

    Вот модель данных:

    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, и я бы хотел понять ГОРМ намного больше. Большое спасибо за вашу помощь.

Ответы [ 3 ]

9 голосов
/ 14 сентября 2011

Попробуйте это

def results =  Car.createCriteria().list() { 
    createAlias('owner','owner')
    projections { 
        property('owner.name', 'owner.name') 
        property('brand','brand')
        property('price','price')
    }
}
3 голосов
/ 28 июня 2011

Для (№ 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()

1 голос
/ 25 апреля 2011

Для (1) и (2) я не знаю, есть ли способ сделать то, что вы хотите, с помощью только одного критерия запроса, но альтернативный способ кажется более простым и естественным. Для (1):

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

Для (2)

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

О (3), это своего рода проблема дизайна здесь. Ваш текущий дизайн домена не отражает правило, которое вы описываете, поэтому будет трудно поддерживать это ограничение. Вы можете рассмотреть отображение таблицы PersonOrganization и сделать childrenOrganization временным свойством . Например:

class Organization {
    int id
    String name
    Organization parent
    static transients = ['children']
    ...

    Boolean children() {
        def children = Organization.createCriteria().list() { 
            eq ('parent', this) 
        }
        return children
    }
}

После этого вы можете использовать функцию трассировки, такую ​​как getAllAncestors (), чтобы определить всю родительскую иерархию организации, найти ее в списке человек-организация. Это кажется не лучшим способом, но это возможный путь.

...