org.hibernate.AnnotationException: referencedColumnNames 引用未映射到单个属性

2022-09-03 06:07:27

我在映射2个实体之间的一对一时遇到了以下异常。第 1 个实体具有嵌入式复合键。第二个实体还具有嵌入式复合键。这些表是旧系统的一部分。数据是平面的,关系没有很好地定义。请帮忙。

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;

答案 1

问题的原因是您尝试使用单个联接列,而引用的实体的标识由多个列定义。您只需要定义所有需要的联接 colum,就可以开始了:

@JoinColumns({
   @JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME"),
   @JoinColumn(name = "OTHER_KEY", referencedColumnName = "SOME_OTHER_NAME"))
   ...
})
MnEditFlag mnEditFlag;

OT:注释上不需要属性。这已由目标实体的类型定义:。您可能只需要未键入 。targetEntityOneToOneMnEditFlagtargetEntityCollections

编辑:如果有单个联接列,它只是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 列添加数据,如上所述。

编辑3:我推荐的策略是基于您希望拥有完整的CRUD功能的建议。如果您只想提取数据以进行显示或报告,则视图完全没问题。您可以定义所需的列,并将整个视图映射到单个实体。但是,由于它是一个视图,因此您将无法更改数据或迁移数据。


答案 2

您可以在@ManyToOne上使用目标实体。目标实体应等于父类(可能是抽象类)。临时解决方案取决于您的类层次结构:https://hibernate.atlassian.net/browse/HHH-4975


推荐