与继承的单向多对一关系
Posted
技术标签:
【中文标题】与继承的单向多对一关系【英文标题】:unidirectional many to one relationship with inheritance 【发布时间】:2015-04-15 01:44:04 【问题描述】:我试图在休眠中映射class ED
和class TEL
之间的多对一关系,但是当我在eclipse 中尝试Run As.. Run on server
时出现以下错误:
Caused by: org.hibernate.MappingException: Could not determine type for:
my.package.name.TEL, at table: ed, for columns:
[org.hibernate.mapping.Column(reference)]
如何解决此错误? ED 类只有一个 TEL 属性,但 TEL 类在许多其他类中用作属性,因此将其设为双向关系是没有意义的。我永远不需要查找与给定 TEL 关联的所有 ED 对象。 大多数 TEL 实例不会与 ED 实例有关系,但所有 ED 实例都会有一个 TEL 属性。我是否正确分类了这种关系?以及如何更改以下代码来解决此错误? 请注意,继承会使事情变得复杂。
这里是 TEL.java:
@Entity(name = "tel")
@Table(name = "tel")
public class TEL extends ANY
private String value;
@Column(name = "value")
public String getValue()return value;
public void setValue(String val)value = val;
这里是 ED.java:
@Entity(name = "ed")
@Table(name = "ed")
public class ED extends ANY
private byte[] data;
private String mediaType;
private String language;
private TEL reference;
@Column(name = "data")
public byte[] getData()return data;
public void setData(byte[] d)data = d;
@Column(name = "mediaType")
public String getMediaType()return mediaType;
public void setMediaType(String mt)mediaType = mt;
@Column(name = "language")
public String getLanguage()return language;
public void setLanguage(String lng)language = lng;
@ManyToOne
@JoinColumn(name = "hppid")
public TEL getReference()return reference;
public void setReference(TEL ref)reference = ref;
这里是 ANY.java:
@Entity(name = "rim_any")
@Table(name = "rim_any")
public class ANY extends BaseEntity
private CS nullFlavor;
public CS getNullFlavor()return nullFlavor;
public void setNullFlavor(CS nf)nullFlavor = nf;
这里是 BaseEntity.java:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'BaseEntity' ELSE dtype END)")
@org.hibernate.annotations.DiscriminatorOptions(force=true)
public abstract class BaseEntity
@Transient
private String dtype = this.getClass().getSimpleName();
@Id
@GeneratedValue(
strategy=GenerationType.TABLE,
generator="TBL_GEN")
@TableGenerator(
name="TBL_GEN",
table="GENERATOR_TABLE",
pkColumnName = "mykey",
valueColumnName = "hi",
pkColumnValue="hppid",
allocationSize=20
)
protected Long hppid;
public void setHppid(Long id) this.hppid = id;
public Long getHppid() return hppid;
public void setDtype(String dt)dtype=dt;
public String getDtype()return dtype;
public boolean isNew() return (this.id == null);
这是我在 Eclipse 中尝试 Run As...Run on server
时抛出的完整堆栈跟踪:
ERROR ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0' defined in class path resource [spring/business-config.xml]: Initialization of bean failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring/business-config.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) ~[spring-context-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) ~[spring-context-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) ~[spring-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) ~[spring-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [spring-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4772) [catalina.jar:8.0.15]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196) [catalina.jar:8.0.15]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.15]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409) [catalina.jar:8.0.15]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399) [catalina.jar:8.0.15]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_71]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_71]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_71]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_71]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring/business-config.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:438) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:277) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) ~[spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:71) ~[spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:85) ~[spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1532) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1500) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
... 19 common frames omitted
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:923) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:898) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:76) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:288) ~[spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310) ~[spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
... 34 common frames omitted
Caused by: org.hibernate.MappingException: Could not determine type for: my.package.name.TEL, at table: ed, for columns: [org.hibernate.mapping.Column(reference)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:314) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.mapping.Property.isValid(Property.java:239) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:469) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.mapping.UnionSubclass.validate(UnionSubclass.java:61) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.cfg.Configuration.validate(Configuration.java:1296) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1752) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:913) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
... 40 common frames omitted
Apr 14, 2015 6:12:45 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0' defined in class path resource [spring/business-config.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring/business-config.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4772)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring/business-config.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:438)
at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:277)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79)
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:71)
at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1532)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1500)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
... 19 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: myapp] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:923)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:898)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:76)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:288)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 34 more
Caused by: org.hibernate.MappingException: Could not determine type for: my.package.name.TEL, at table: ed, for columns: [org.hibernate.mapping.Column(reference)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:314)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292)
at org.hibernate.mapping.Property.isValid(Property.java:239)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:469)
at org.hibernate.mapping.UnionSubclass.validate(UnionSubclass.java:61)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1296)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1752)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:913)
... 40 more
Apr 14, 2015 6:12:45 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
Apr 14, 2015 6:12:45 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/myapp] startup failed due to previous errors
Apr 14, 2015 6:12:45 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Apr 14, 2015 6:12:45 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Apr 14, 2015 6:12:45 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-nio-8009"]
Apr 14, 2015 6:12:45 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 12061 ms
编辑:
我尝试了@VladMihalCea 的建议:
@ManyToOne
@MapsId("hppid")
public TEL getReference()return reference;
在 ED.java 中,但得到了同样的错误。然后我尝试了他的其他建议:
@ManyToOne
@JoinColumn(name = "ref_hppid")
public TEL getReference()return reference;
在 ED.Java 中,但没有对 TEL.java 或任何其他文件进行任何更改。这也给出了相同的堆栈跟踪。
我是否需要对 TEL.java 进行其他更改?我还能尝试什么?
【问题讨论】:
【参考方案1】:Ed
类从 BaseEntity
继承 hppid
列,然后使用多对一关联复制它:
@ManyToOne
@JoinColumn(name = "hppid")
public TEL getReference()return reference;
public void setReference(TEL ref)reference = ref;
如果 FK 是 PK 的补充,您可以简单地将其重命名为 ref_hppid
@JoinColumn(name = "ref_hppid")
如果想让PK和FK共享同一列,需要使用@MapsId
:
@ManyToOne
@MapsId("hppid")
public TEL getReference()return reference;
【讨论】:
很奇怪,当映射发生变化时它并没有改变任何东西。您是否使用 hbmddl 自动生成架构? 应将更改应用于 Ed 表,为 FK 创建一个新列。我不知道还有什么问题。 我不知道。在生产服务器上,您不会像示例中那样过度使用继承。投注映射是最简单的映射,它反映了数据库架构。 这可能会在其他地方引起问题,因为这种模式的性质主要是由外部机构强加的。但我将它展平以使其立即运行,以便我可以测试其他东西。让我们看看其他人是否有任何想法。我对你的一些其他答案给出了+1,这些答案根据他们自己的优点来证明,作为对帮助我提出这个问题的感激之情。谢谢。 也谢谢你。奇怪的是它没有找到 Ted,因为那是一个具体的类。通常这个错误是由于使用了一个接口。以上是关于与继承的单向多对一关系的主要内容,如果未能解决你的问题,请参考以下文章