Проблема дискриминатора в отображении наследования Grails
У меня есть 4 класса A, B, B1, B2 с отображением наследования, описанным ниже:
A (сопоставленный с таблицей A) - самый верхний родительский класс, и его стратегия отображения наследования tablePerHierarchy=false
(означает, что каждый из его подклассов сопоставлен с одной таблицей).
Класс B простирается от A, а B1, B2 простирается от B. Но B1 и B2 совместно используют одну и ту же таблицу с B, поэтому в классе B я заявляю tablePerHierarchy=true
и дискриминатор для разделения B1 и B2.
Подробный код здесь:
class A {
static mapping = {
tablePerHierarchy false
table 'A'
}
}
class B extends A {
static mapping = {
tablePerHierarchy true
table 'B'
discriminator column : 'TYPE'
}
String bProp1
String bProp2
}
class B1 extends B {
static mapping = {
discriminator column : 'TYPE', value : 'B1'
}
String b1Props1
String b1Props2
}
class B2 extends B {
static mapping = {
discriminator column : 'TYPE', value : 'B2'
}
String b2Props1
String b2Props1
}
Когда я запускаю свое приложение, произошла ошибка:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageSource': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: No discriminator found for edu.test.B1. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:212)
at grails.web.container.EmbeddableServer$start.call(Unknown Source)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
at RunApp$_run_closure1.doCall(RunApp:33)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: No discriminator found for edu.test.B1. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
... 23 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: No discriminator found for edu.test.B1. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
... 23 more
Caused by: org.hibernate.MappingException: No discriminator found for edu.test.B1. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
... 23 more
Я следовал инструкциям документации Grails о дискриминаторе ( http://grails.org/doc/latest/ref/Database%20Mapping/discriminator.html), но он не работал. Я нашел JIRA об этой проблеме документа здесь: http://jira.grails.org/browse/GRAILS-5168 и исправил мой код, когда они комментируют, но он все еще получил ту же ошибку.
Я не знаю причину, вызвавшую эту проблему. Заменяет ли tablePerHierarchy=true в B стратегию, определенную в A?
Не могли бы вы помочь мне решить эту проблему? Огромное спасибо.
1 ответ
Кажется, что смешение стратегий наследования для иерархии классов не поддерживается, даже до уровня JPA/Hibernate. Я думаю, что ваша проблема такая же (или, по крайней мере, очень похожа) на эти:
Изменение стратегии наследования в ветвях иерархии классов с помощью аннотаций JPA
Как смешать стратегии наследования с аннотациями JPA и Hibernate?
Если вы измените параметры ведения журнала для 'org.codehaus.groovy.grails.orm.hibernate' на 'debug', вы увидите, что параметр tablePerHierarchy = true в классе B НЕ переопределяет стратегию в A. Несмотря на это, он не не работает Опять же, это выглядит как ограничение на более низком уровне, чем GORM. Может ли ваш проект пересмотреть, чтобы использовать одну стратегию наследования для этой иерархии?