Grails: проекция на множество таблиц?

У меня проблемы с проекцией в 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, Пертер, 01 улица А, [Мерседес, Тойота, Дукатти]]?

  3. Особая ситуация: (с вышеприведенным классом Person)
    Человек может присоединиться ко многим организациям, а организация может иметь одну "родительскую" организацию (и наоборот, организация может иметь много других зависимых организаций). Но есть правило: человек может вступить только в одну дочернюю организацию данной организации. Итак, для данной организации O и человека P, каков самый быстрый способ получить информацию о P вместе с названием организации, зависящей от O, членом которой является P. Я предпочитаю использовать проекцию 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. Большое вам спасибо за вашу помощь.


person Đinh Hồng Châu    schedule 24.04.2011    source источник


Ответы (3)


Для (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(), чтобы определить всю родительскую иерархию организации и найти ее в списке человек-организация. Это кажется не лучшим способом, но это возможный путь.

person Hoàng Long    schedule 25.04.2011

Попробуй это

def results =  Car.createCriteria().list() { 
    createAlias('owner','owner')
    projections { 
        property('owner.name', 'owner.name') 
        property('brand','brand')
        property('price','price')
    }
}
person Muhammad Aamir Talib    schedule 14.09.2011
comment
Зачем понадобился alias? - person Alexander Suraphel; 08.07.2015
comment
@AlexanderSuraphel без псевдонима вы не можете получить доступ к owner.name напрямую в property('owner.name', 'owner.name') Даже вы можете получить вышеуказанные результаты без псевдонима, но для этого вам нужно написать больше кода. см. ниже пример projections { owner { property('name', 'name') } property('brand','brand') property('price','price') } Пожалуйста, дайте мне знать, если у вас все еще есть какие-либо сомнения, или это был неправильный ответ для вас. Спасибо - person Muhammad Aamir Talib; 15.10.2015
comment
@AlexanderSuraphel Если вы можете написать приведенный выше код без createAlias('owner', 'owner'), возможно, это возможно в более новых версиях Grails. - person Muhammad Aamir Talib; 15.10.2015

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

person Daxon    schedule 28.06.2011