Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

org.hibernate.AnnotationException: referencedColumnNames referencing not mapped to a single property

I ran into the below exception while mapping a one-to-one between 2 entities. The 1 first entity has embedded composite key. The second entity also has embedded composite key. The tables are part of legacy system. Data is flat, relations are not well defined. Please help.

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

Here is my one to one mapping in the main/parent table.

@OneToOne(targetEntity = MnEditFlag.class, fetch = FetchType.LAZY)
@JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME", insertable = false,     updatable = false)
MnEditFlag mnEditFlag;
like image 664
Superman9999 Avatar asked Feb 03 '14 19:02

Superman9999


2 Answers

The cause of the issue is that you are trying to use a single join column, while the identity of the referenced entity is defined by multiple columns. You simply have to define all the needed join colums and you are good to go:

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

OT: you should not need the targetEntity attribute on the OneToOne annotation. This is already defined by the type of the target entity: MnEditFlag. You probably need targetEntity only for untyped Collections.

EDIT: If there is a single join column, which is only part of the PK and you cannot change the existing tables, perhaps you can define a new join table with all necessary columns.

Then you define the join table to be used for the relationship:

@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;  

You would have to migrate the data to the new join table programmatically or by queries.

Unfortunately you cannot define a relationship with a partial PK with vanilla JPA, perhaps Hibernate has such a feature, like one-to-one by query, but I cannot confirm it.

EDIT2: The join table should contain all PK columns for both entities to be fully functional. That is why I have defined two join columns for each side in my example. The number of columns and their names are purely exemplary.

Extracting only the one join column you already have in your table would not add any value.

The optimal solution would be to change the entity tables so they define a proper relationship between the entities. It is sufficient to change only one of the tables and define it as the owning side as you did, but with all FK columns. This would require a migration effort, since you would need to add the data for the missing FK columns like described above.

EDIT3: The strategies I recommended were based on the assubmption that you want to have complete CRUD functionality. If you just want to pull the data for display or reporting, a view is perfectly fine. You can define the columns you need and map the whole view to a single entity. However, as it is a view, you will not be able to change the data or migrate it.

like image 162
kostja Avatar answered Oct 23 '22 02:10

kostja


You could use targetEntity on @ManyToOne. The targetEntity should be equal to the parent (probably abstract) class. The temporary solution is here depending to your class hierarchy: https://hibernate.atlassian.net/browse/HHH-4975

like image 38
Youness Avatar answered Oct 23 '22 00:10

Youness