Beware of the following DB design:
NOTE: Never mind what the creator of this “design” had in mind, but I cannot change it.
It’s about the relationship between MobileTans
and Authenticators
…
The respective mappings of the MobileTans
table:
@Entity
@Table(name="MobileTans")
public class MobileTan implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name="ID", insertable=false, updatable=false)
private Integer id; // dupe read-only field, ID already in relationship below (writable)
@Basic(optional=false)
@Column(name="MOBILE_PHONE_NBR")
private String mobilePhoneNbr;
@Basic
@Column(name="ACTIVATION_CODE")
private String activationCode;
@Basic
@Column(name="ACTIVATION_ERROR")
private Boolean activationError = Boolean.FALSE;
@Basic
@Column(name="STATUS")
private Integer status;
@OneToOne(optional=false, fetch=FetchType.EAGER)
@JoinColumn(name="ID", referencedColumnName="ID")
@JoinColumn(name="AUTH_NAME", referencedColumnName="AUTHENTICATOR")
private Authenticator authenticator;
...
}
The clue here is the duplicate read-only mapping (insertable=false, updatable=false
) for the @Id
column.
The ID
column is defined to be the PK, so there’s no use in setting the @Id
onto the relationship. I must create an extra column mapping. I put the read-only on the extra column, because Hibernate (or JPA) won’t let me specify read-only only on parts of a relationship (I think this is forbidden by the JPA spec).
When launching the server, I get a mapping exception from Hibernate:
00:37:53,979 INFO [org.hibernate.Version] (ServerService Thread Pool -- 72) HHH000412: Hibernate Core {5.3.6.Final}
00:37:53,980 INFO [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 72) HHH000206: hibernate.properties not found
00:37:54,088 INFO [org.hibernate.annotations.common.Version] (ServerService Thread Pool -- 72) HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
00:37:54,382 INFO [org.hibernate.validator.internal.util.Version] (MSC service thread 1-2) HV000001: Hibernate Validator 6.0.13.Final
00:37:54,621 INFO [org.jboss.weld.Version] (MSC service thread 1-3) WELD-000900: 3.0.5 (Final)
00:37:54,674 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 72) WFLYCLINF0002: Started client-mappings cache from ejb container
00:37:54,777 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 72) WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service 'mappingbug.war#BBStatsPU'
00:37:54,806 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 72) HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
00:37:54,859 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl] (ServerService Thread Pool -- 72) Envers integration enabled? : true
00:37:55,007 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 72) MSC000001: Failed to start service jboss.persistenceunit."mappingbug.war#BBStatsPU": org.jboss.msc.service.StartException in service jboss.persistenceunit."mappingbug.war#BBStatsPU": javax.persistence.PersistenceException: [PersistenceUnit: BBStatsPU] Unable to build Hibernate SessionFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:195)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:125)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:650)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:209)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: BBStatsPU] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1016)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:942)
at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:167)
... 9 more
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: net.bbstats.entity.MobileTan column: ID (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:862)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:880)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:902)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:634)
at org.hibernate.mapping.RootClass.validate(RootClass.java:267)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:347)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:466)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939)
... 11 more
00:37:55,011 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "mappingbug.war")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"mappingbug.war#BBStatsPU\"" => "javax.persistence.PersistenceException: [PersistenceUnit: BBStatsPU] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: BBStatsPU] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: net.bbstats.entity.MobileTan column: ID (should be mapped with insert=\"false\" update=\"false\")"}}
00:37:55,018 INFO [org.jboss.as.server] (ServerService Thread Pool -- 42) WFLYSRV0010: Deployed "mappingbug.war" (runtime-name : "mappingbug.war")
00:37:55,019 INFO [org.jboss.as.controller] (Controller Boot Thread) WFLYCTL0183: Service status report
WFLYCTL0186: Services which failed to start: service jboss.persistenceunit."mappingbug.war#BBStatsPU": javax.persistence.PersistenceException: [PersistenceUnit: BBStatsPU] Unable to build Hibernate SessionFactory
WFLYCTL0448: 19 additional services are down due to their dependencies being missing or failed
00:37:55,079 INFO [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Resuming server
00:37:55,081 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
00:37:55,081 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
00:37:55,082 ERROR [org.jboss.as] (Controller Boot Thread) WFLYSRV0026: WildFly Full 14.0.1.Final (WildFly Core 6.0.2.Final) started (with errors) in 14146ms - Started 449 of 645 services (23 services failed or missing dependencies, 328 services are lazy, passive or on-demand)
BTW, I am using Hibernate Core 5.3.6.Final on Wildfly 14.
QUESTION:
What’s wrong here? Why does Hibernate complain about this? My impression is that this is perfectly legal.
Help greatly appreciated!
Kawu