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 并在他们评论时修复了我的代码,但仍然出现相同的错误。
我不知道导致这个问题的原因。 B 中的 tablePerHierarchy=true 是否会覆盖 A 中定义的策略?
你能帮我解决这个问题吗?太感谢了。
I have 4 classes A, B, B1, B2 with inheritance mapping described as below:
A (mapped to table A) is the top-most parent class and its inheritance mapping strategy is tablePerHierarchy=false
(means each of its sub-classes is mapped to a single table).
Class B extends from A, and B1, B2 extends from B. But B1 and B2 share the same table with B, so in B class, I declare tablePerHierarchy=true
and a discriminator to separate B1 and B2.
The detail code is here:
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
}
When I start my app, there's an error occured:
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
I have followed the instruction of Grails documentation about discriminator ( http://grails.org/doc/latest/ref/Database%20Mapping/discriminator.html ) but it did not work. I have found a JIRA about this document issue here: http://jira.grails.org/browse/GRAILS-5168 and fixed my code as they comment but it still got the same error.
I do not know the reason which caused this issue. Does the tablePerHierarchy=true in B override that strategy defined in A?
Could you please help me to fix this problem? Thank you so much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
似乎并没有真正支持类层次结构的混合继承策略,甚至到 JPA/Hibernate 级别也是如此。
我认为您的问题与这些相同(或至少非常相似):
通过 JPA 注释更改类层次结构分支中的继承策略
如何将继承策略与 JPA 注释和 Hibernate 混合使用?
如果将“org.codehaus.groovy.grails.orm.hibernate”的日志设置更改为“debug”,您可以看到B 类中的“tablePerHierarchy=true”设置不会覆盖 A 中的策略。无论如何,它不起作用。同样,它看起来是一个比 GORM 级别更低的限制。可以修改您的设计以对该层次结构使用一种继承策略吗?
It seems that mixing inheritance strategies for a class hierarchy is not really supported, even down to the JPA/Hibernate level.
I think your issue is the same as (or at least very similar to) these:
Changing the inheritance strategy in branches of the class hierarchy via JPA annotations
How to mix inheritance strategies with JPA annotations and Hibernate?
If you change the logging settings for 'org.codehaus.groovy.grails.orm.hibernate' to 'debug' you can see that the 'tablePerHierarchy=true' setting in class B does NOT override the strategy in A. Regardless, it doesn't work. Again, it looks to be a limitation at a lower level than GORM. Can revise your design to use one inheritance strategy for that hierarchy?