Запрос критериев Gorm для получения двух отношений один-ко-многим, fetchMode не работает - PullRequest
0 голосов
/ 22 января 2019

У меня есть модель домена - в Org много сайтов и много доменов (это два атрибута коллекции bag).

Я хочу написать запрос, который извлекает один, а предпочтительно, сайты и коллекции доменов в одном хите.

Я попробовал это сначала

org = Org.findById (id, [fetch:[sites:"eager", domains:"eager"]]

, что не с

не может одновременно получать несколько пакетов: [com.softwood.domain.OrgRoleInstance.sites, com.softwood.domain.OrgRoleInstance.domains]

(будет работать только с одной из двух коллекций).

Я попробовал запрос критерия, подобный этому

    org = resource.withCriteria (uniqueResult: true) {
        fetchMode 'sites', FetchMode.SELECT
        fetchMode 'domains', FetchMode.SELECT
        idEq(id)
        sites {
            org {
                eq 'id', "$id"
            }
        }

    } // didn't work 

какие ошибки с этим

Нет подписи метода: com.softwood.controller.OrgRoleInstanceController.fetchMode () применим к типам аргументов: (java.lang.String, org.hibernate.annotations.FetchMode) значения: [sites, SELECT]

Это указывает на то, что ей не нравится функция fetchMode (с использованием SELECT или JOIN).

Как написать запрос критерия, который возвращает один сопоставленный объект по идентификатору, но одновременно возвращает сайты и коллекции доменов?

Класс домена выглядит следующим образом. Я не хочу использовать статическое отображение = {} замыкание - поскольку я хочу контролировать загрузку путем написания явных запросов по мере необходимости

class Org {

    enum OrgRoleType {
        Supplier,
        Customer,
        Service_Provider,
        Manufacturer,
        Maintainer,
        Indeterminate
    }

    String name
    OrgRoleType role
    Collection<NetworkDomain> domains = []
    Collection<Site> sites = []
    Collection<MaintenanceAgreement> mags       //optional only set if role is service provider
    //Collection<Device> ci

     static hasMany = [domains : NetworkDomain, sites: Site, mags:MaintenanceAgreement]

    static mappedBy  = [mags: "maintainer"]  //disambiguate column in mags


    static constraints = {
        name nullable:false
        role  nullable:true
        domains nullable:true
        sites nullable:true
        mags nullable:true  //optional
    }
}

Я видел это [ Grails GORM Критерий Query Eager Fetching

Я пытался сделать то же самое, но fetchMode (String, enum) просто не запускается.

Обновление

Я изменил запрос на этот

    org = resource.withCriteria (uniqueResult: true) {
        join 'sites' 
        join  'domains' 
        idEq(id)
        sites {
            org {
                eq 'id', "$id"
            }
        }
        domains {
            customer {
                eq 'id', "$id"
            }
        }

    }

Это ошибки с

Cannot invoke method call() on null object

с трассировкой, указывающей на точку доступа к сайтам {org {в критериях.

1 Ответ

0 голосов
/ 24 января 2019

, поэтому первое тестирование должно быть выполнено в виде интеграционных тестов, а не модульных тестов, однако в результате вы все равно не можете выполнить поиск запросов с двумя активными нагрузками. если вы хотите загрузить коллекции, вы должны использовать критерии или, возможно, предложение where для этого

здесь два интеграционных теста - первый с использованием искателей завершается с ошибкой, второй достигает цели с помощью запроса критерия

void "query by finderById with multiple eager fetch in map conditions " () {

    given :


    when: "we print value from a collection "

    def org = OrgRoleInstance.findById (7L, [fetch:[sites:"eager", domains:"eager"]])
    println org.domains[0].name

    then:
    org.hibernate.loader.MultipleBagFetchException ex = thrown()


}

void "query withCriteria to do  multiple eager fetch in map conditions " () {

    given :


    def org = OrgRoleInstance.withCriteria (uniqueResult: true) {
        fetchMode 'sites', FetchMode.SELECT
        fetchMode 'domains', FetchMode.SELECT
        idEq (7L)
        sites {}
        domains {}

    }


    when: "we print value from a collection "

    println org.domains[0].name

    then:
    org.domains.size() == 1
    org.sites.size() == 2


}
...