I have two given tables (posgres) with the following fields (all big ints):
Transaction:
Reversal:
There is an optional 1:1 relationship between Transaction and Reversal: Transaction exists always; Reversal exists, if the transaction has been reversed. The relationship is done with a composite foreign key in reversal (reader_id, trxref). The tables are given this way and I need to map them in JPA. I need to map Reversal in Transaction that I can navigate in named queries i.e. SELECT FROM Transaction t LEFT JOIN t.reversal rv ....
So what I do is:
@Entity
@Table(
indexes = {
@Index(columnList = "readerTrxRef,reader_id", unique = true),
}
)
public class Transaction
{
static final Long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long transactionid;
private Long reader_id;
private Long readertrxref
@OneToOne(fetch = FetchType.EAGER, mappedBy = "transaction")
private Reversal reversal;
...
}
@Entity
@Table(
indexes = {
@Index(columnList = "readerID,trxRef", unique = true),
}
)
public class Reversal
{
static final Long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private Integer trxref;
private Long readerid;
public Integer getTrxRef()
{
return trxRef;
}
@OneToOne
@JoinColumns(
{
@JoinColumn(updatable = false, insertable = false, name = "readerid", referencedColumnName = "reader_id"),
@JoinColumn(updatable = false, insertable = false, name = "trxref", referencedColumnName = "readertrxref"),
}
)
private Transaction transaction;
During deployment, I get the following exception:
14:24:12,455 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 24) MSC000001: Failed to start service jboss.persistenceunit."ROOT.war#primary": org.jboss.msc.service.StartException in service jboss.persistenceunit."ROOT.war#primary": javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:179)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:121)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:193)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882)
at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:161)
... 7 more
Caused by: org.hibernate.MappingException: broken column mapping for: reversal.transaction of: ch.microtronic.evending.web.model.entities.Transaction
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:165)
at org.hibernate.persister.entity.AbstractPropertyMapping.initIdentifierPropertyPaths(AbstractPropertyMapping.java:253)
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:219)
at org.hibernate.persister.entity.AbstractEntityPersister.initOrdinaryPropertyPaths(AbstractEntityPersister.java:2194)
at org.hibernate.persister.entity.AbstractEntityPersister.initPropertyPaths(AbstractEntityPersister.java:2241)
at org.hibernate.persister.entity.AbstractEntityPersister.postConstruct(AbstractEntityPersister.java:3790)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:437)
at sun.reflect.GeneratedConstructorAccessor62.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:346)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
... 9 more
Can anybody point me to the fault? I just tried to remove @JoinColumns
and to have just one @JoinColumn
. In this case, I can deploy the application - this shows me that it is a strange error and I am not very amazed, if it is a bug in hibernate even though I thougth this is a not very exotic use case. (we use Hibernate 5.2.12 in Wildfly 10.1.0).
Edit Clarified that the mapping is transaction(reader_id, readertrxref)->reversal(readerid, trxref) and that this is given this way. I need to map it this way and I cannot use transactionid as foreign key in reversal because it does (due to technical reason) not exist in this table.
It is not possible to solve that. As Tom and DN1 pointed out, JoinColumns must be on the PKs. Since they are not the PKs in my use case and I cannot make them to be a composite PK (because the relation Transaction->Reversal is optional and thus, I still need a real PK i.e. transactionID), it seems not to be possible to solve this with JPA.