我在2个实体之间映射一对一时遇到了以下异常。第一个实体嵌入了复合键。第二个实体也有嵌入式复合键。这些表是遗留系统的一部分。数据持平,关系定义不明确。请帮忙。
Caused by: org.hibernate.AnnotationException: referencedColumnNames(FLAG_NAME) of net.javabeat.spring.model.ReferralsM.mnEditFlag referencing net.javabeat.spring.model.MnEditFlag not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:205)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1515)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1440)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1358)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1727)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1778)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:247)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:373)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 34 more
这是我在主/父表中的一对一映射。
@OneToOne(targetEntity = MnEditFlag.class, fetch = FetchType.LAZY)
@JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME", insertable = false, updatable = false)
MnEditFlag mnEditFlag;
答案 0 :(得分:14)
问题的原因是您尝试使用单个连接列,而引用实体的标识由多个列定义。你只需要定义所有需要的连接列,你就可以了:
@JoinColumns({
@JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME"),
@JoinColumn(name = "OTHER_KEY", referencedColumnName = "SOME_OTHER_NAME"))
...
})
MnEditFlag mnEditFlag;
OT:您不应该在targetEntity
注释上使用OneToOne
属性。这已由目标实体的类型定义:MnEditFlag
。对于无类型targetEntity
,您可能只需要Collections
。
编辑:如果只有一个连接列,它只是PK的一部分而你无法更改现有的表,那么你可以定义一个包含所有必要列的新连接表。
然后定义用于关系的连接表:
@JoinTable(name="ReferralsM_MnEditFlag",
joinColumns={
@JoinColumn(name="REFERRALS_ID1", referencedColumnName="ID1"),
@JoinColumn(name="REFERRALS_ID2", referencedColumnName="ID2")
}, inverseJoinColumns={
@JoinColumn(name="REFFLG", referencedColumnName="FLAG_NAME"),
@JoinColumn(name="REFFLG2", referencedColumnName="FLAG_NAME2")
})
MnEditFlag mnEditFlag;
您必须以编程方式或通过查询将数据迁移到新的连接表。
不幸的是,你无法使用vanilla JPA定义与部分PK的关系,也许Hibernate有这样的功能,比如查询一对一,但我无法确认。
EDIT2:联接表应包含两个实体的所有PK列才能完全正常运行。这就是为什么我在我的示例中为每一侧定义了两个连接列。列数及其名称纯粹是示例性的。
仅提取表中已有的一个连接列不会添加任何值。
最佳解决方案是更改实体表,以便它们定义实体之间的正确关系。仅更改其中一个表并将其定义为拥有方就足够了,但使用所有FK列。这需要迁移工作,因为您需要为缺少的FK列添加数据,如上所述。
EDIT3:我推荐的策略基于您希望拥有完整CRUD功能的提示。如果您只想提取数据进行显示或报告,那么视图就可以了。您可以定义所需的列,并将整个视图映射到单个实体。但是,由于它是一个视图,您将无法更改数据或迁移它。
答案 1 :(得分:0)
您可以在@ManyToOne上使用targetEntity。 targetEntity应该等于父(可能是抽象)类。 临时解决方案取决于您的类层次结构: https://hibernate.atlassian.net/browse/HHH-4975