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;
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With