Я использую Grails v3.3.9.
Я не могу получить запросы для активной загрузки связи один-ко-многим. Перепробовал всевозможные способы.
Это сообщение относится к попытке использовать его в модульном тестировании (также не работает в приложении во время выполнения).
Сценарий. У меня есть два класса доменов, один из которых называется OrgRoleInstance с Collection<Site>
сайтами и static hasMany =[sites:Site]
, а другой называется 'Site' с static belongsTo = [org:OrgRoleInstance]
.
Это перенаправленный один-ко-многим от организаций к сайтам.
Я создаю новый модульный тест, используя новую черту DomainUnitTest. В тестовой настройке я создаю три организации и добавляю по одному сайту каждый, затем добавляю один последний сайт в 3-ю организацию (org "C"). Программа установки работает нормально, и все экземпляры сохраняются.
В тесте запроса where я ищу организацию, которая имеет 2 сайта (это org "C").
Когда я запускаю тест в режиме отладки, запрос where возвращает массив размера 1, содержащий org "C", поэтому тест в предложении where может видеть, что семейство сайтов не равно нулю - пока все хорошо.
Я также делаю прямой Site.get (4), чтобы получить последний сайт. Я делаю проверку assert, чтобы убедиться, что ссылка sites.org - это тот же экземпляр, который был возвращен из запроса where. Это правда и проходит.
Однако, когда вы смотрите на запись orgs [0], коллекция сайтов пуста. Это простое println не удается получить доступ к свойству null sites, возвращенному из запроса.
class OrgRoleInstanceSpec extends Specification implements DomainUnitTest<OrgRoleInstance> {
def setup() {
OrgRoleInstance
List<OrgRoleInstance> orgs = []
["A","B","C"].each {
OrgRoleInstance org = new OrgRoleInstance(name:it, role:OrgRoleInstance.OrgRoleType.Customer)
org.addToSites(new Site( name: "$it's Head Office", status:"open", org:org))
orgs << org
}
orgs[2].addToSites (new Site( name: "${orgs[2].name}'s Branch Office", status:"open", org:orgs[2]))
OrgRoleInstance.saveAll(orgs)
assert OrgRoleInstance.count() == 3
println "# of sites : " + Site.count()
assert Site.count() == 4
assert Site.get(2).org.id == orgs[1].id
}
void "where query and individual get " () {
given :
def orgs = OrgRoleInstance.where {
sites.size() == 2
}.list(fetch:[sites:"eager"])
def org = OrgRoleInstance.get(2)
List orgSites = org.sites
def branch = Site.get(4)
assert branch.org.is (orgs[0]) //assert is true
println orgs[0].sites[1].name //orgs[0].sites is null !
expect:
orgs.size() == 1
}
}
Я пробовал это с критериями, с основными findAll(fetch:[sites:"eager")
и т. Д.
Однако я пытаюсь это сделать, но не могу получить запрос на возврат нетерпеливо заполненной коллекции сайтов.
Я хочу сделать это в запросах, а не путем сопоставления предложения в классе домена OrgeRoleInstance
Обновление / наблюдения
Я включил ведение журнала SQL и запустил консоль grails. Затем я набрал следующий скрипт (используя данные начальной загрузки).
Консольный скрипт, введенный вручную
import com.softwood.domain.*
def orgs = OrgRoleInstance.where {
id == 4
sites{}
}.list() /* (fetch:[sites:"eager"]) */
println orgs[0].sites
, который при запуске выдает следующее - которое, по сути, действительно запускает активный выбор - и я получаю результат orgs.sites с заполненными записями с использованием внутреннего соединения:
groovy> import com.softwood.domain.*
groovy> def orgs = OrgRoleInstance.where {
groovy> id == 4
groovy> sites{}
groovy> }.list() /* (fetch:[sites:"eager"]) */
groovy> println orgs[0].sites
2019-01-23 14:02:00.923 DEBUG --- [ Thread-18] org.hibernate.SQL :
select
this_.id as id1_16_1_,
this_.version as version2_16_1_,
this_.role as role3_16_1_,
this_.name as name4_16_1_,
sites_alia1_.id as id1_21_0_,
sites_alia1_.version as version2_21_0_,
sites_alia1_.org_id as org_id3_21_0_,
sites_alia1_.name as name4_21_0_,
sites_alia1_.status as status5_21_0_
from
org_role_instance this_
inner join
site sites_alia1_
on this_.id=sites_alia1_.org_id
where
this_.id=?
2019-01-23 14:02:00.923 TRACE --- [ Thread-18] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [4]
2019-01-23 14:02:00.923 DEBUG --- [ Thread-18] org.hibernate.SQL :
select
sites0_.org_id as org_id3_21_0_,
sites0_.id as id1_21_0_,
sites0_.id as id1_21_1_,
sites0_.version as version2_21_1_,
sites0_.org_id as org_id3_21_1_,
sites0_.name as name4_21_1_,
sites0_.status as status5_21_1_
from
site sites0_
where
sites0_.org_id=?
2019-01-23 14:02:00.923 TRACE --- [ Thread-18] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [4]
[Site:(name : 1 Barkley Square) belonging to org: com.softwood.domain.OrgRoleInstance : 4, Site:(name : 10 South Close) belonging to org: com.softwood.domain.OrgRoleInstance : 4]
Так почему же это не работает в модульном тестировании?
Еще одно обновление
Я вернулся в консоль grails и смог заставить этот запрос критерия работать. Точка 1 - вы должны были импортировать org.hibernate.FetchMode
, тогда функция fetchMode на корневом уровне в withCriteria будет работать теперь. Наконец, просто сделайте пустое закрытие в коллекции, чтобы вызвать активный запрос.
import com.softwood.domain.*
import org.hibernate.FetchMode
def orgs = OrgRoleInstance.withCriteria {
fetchMode ("sites", FetchMode.SELECT)
sites{}
}
println orgs[0].sites
Однако это не работает в модульном тесте. Тот же запрос в модульном тесте, как этот
void "criteria query " () {
given:
OrgRoleInstance org
org = OrgRoleInstance.withCriteria (uniqueResult: true) {
fetchMode ("sites", FetchMode.SELECT)
sites{}
}
expect:
org.id == 3
org.sites.size() == 2
}
не с этой ошибкой
groovy.lang.MissingMethodException: No signature of method: grails.gorm.CriteriaBuilder.fetchMode() is applicable for argument types: (java.lang.String, org.hibernate.FetchMode) values: [sites, SELECT]
Поэтому я подозреваю, что критерии модульного тестированияQueries или где запросы с использованием новых grails DomainUnitTest<T>
черта не поддерживает запросы соединения / ожидания и т. Д.
Возможно, вы вынуждены проводить интеграционные тесты с реальной БД для проверки запросов к таблицам. Если кто-то может категорически заявить, что новые черты модульного тестирования не работают для запросов на соединение / нетерпение, которые могут мне помочь.