Reputation: 11
I have 3 JPA entities with joined inheritance (1 superclass and 2 subclasses) and there is one to one relationship beetwen subclasses depending on superclass field.
And I have a problem with relationship declaration.
Tables:
create table Parent (
id int primary key,
guid uuid
);
create table A (
id int primary key references Parent(id),
some_a_specific_field text
);
create table B (
id int primary key references Parent(id),
some_b_specific_field text,
a_guid uuid
);
Entities:
@Data
@NoArgsConstructor
@Entity
@Table(name = "Parent")
@Inheritance(strategy = InheritanceType.JOINED)
public class ParentEntity {
@Id
private Integer id;
private UUID guid;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "A")
public class AEntity extends ParentEntity {
private String someASpecificField;
@OneToOne
private BEntity b;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "B")
public class BEntity extends ParentEntity {
private String someBSpecificField;
}
I've tried several ways to declare relationship and got error with each of them.
First: With unidirectional and @JoinColumn.
Entity:
@Data
@NoArgsConstructor
@Entity
@Table(name = "A")
public class AEntity extends ParentEntity {
private String someASpecificField;
@OneToOne
@JoinColumn(name = "guid", table = "Parent", referencedColumnName = "a_guid", insertable = false, updatable = false)
private BEntity b;
}
Error:
Caused by: org.hibernate.AnnotationException: Cannot find the expected secondary table: no Parent available for AEntity
Second: With unidirectional, @JoinColumn and @SecondaryTable.
Entity:
@Data
@NoArgsConstructor
@Entity
@Table(name = "A")
@SecondaryTable(name = "Parent")
public class AEntity extends ParentEntity {
private String someASpecificField;
@OneToOne
@JoinColumn(name = "guid", table = "Parent", referencedColumnName = "a_guid", insertable = false, updatable = false)
private BEntity b;
}
Error:
Caused by: org.hibernate.MappingException: Could not instantiate persister org.hibernate.persister.entity.JoinedSubclassEntityPersister
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:112)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:181)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:319)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1498)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
... 90 more
Caused by: java.lang.IllegalStateException: Encountered 'subclass table index' [-1] was outside expected range ( [0] < i < [5] )
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.associateSubclassNamesToSubclassTableIndex(JoinedSubclassEntityPersister.java:697)
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.associateSubclassNamesToSubclassTableIndexes(JoinedSubclassEntityPersister.java:681)
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.processPersistentClassHierarchy(JoinedSubclassEntityPersister.java:657)
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.processPersistentClassHierarchy(JoinedSubclassEntityPersister.java:639)
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.buildSubclassNamesBySubclassTableMapping(JoinedSubclassEntityPersister.java:621)
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.<init>(JoinedSubclassEntityPersister.java:561)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96)
... 98 more
Third: With bidirectional
Entities:
@Data
@NoArgsConstructor
@Entity
@Table(name = "A")
public class AEntity extends ParentEntity {
private String someASpecificField;
@OneToOne(mappedBy = "a")
private BEntity b;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "B")
public class BEntity extends ParentEntity {
private String someBSpecificField;;
@OneToOne
@JoinColumn(name = "a_guid", referencedColumnName = "guid")
private AEntity a;
}
Error:
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.util.UUID Parent.guid] by reflection for persistent property [Parent#guid] : 1
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:59) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.type.ComponentType.getPropertyValue(ComponentType.java:419) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:246) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.spi.EntityUniqueKey.generateHashCode(EntityUniqueKey.java:67) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.spi.EntityUniqueKey.<init>(EntityUniqueKey.java:48) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:757) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:468) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.internal.TwoPhaseLoad$EntityResolver.lambda$static$0(TwoPhaseLoad.java:576) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityEntryLoadedState(TwoPhaseLoad.java:221) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:155) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:126) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1201) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.processResultSet(Loader.java:1009) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:967) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:357) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2868) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2850) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2682) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.Loader.list(Loader.java:2677) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:540) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1459) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.query.Query.getResultList(Query.java:165) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:76) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:128) ~[spring-data-jpa-2.6.4.jar:2.6.4]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90) ~[spring-data-jpa-2.6.4.jar:2.6.4]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155) ~[spring-data-jpa-2.6.4.jar:2.6.4]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143) ~[spring-data-jpa-2.6.4.jar:2.6.4]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.6.4.jar:2.6.4]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.6.4.jar:2.6.4]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:159) ~[spring-data-commons-2.6.4.jar:2.6.4]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138) ~[spring-data-commons-2.6.4.jar:2.6.4]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.19.jar:5.3.19]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.6.4.jar:2.6.4]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.19.jar:5.3.19]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.19.jar:5.3.19]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.19.jar:5.3.19]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.19.jar:5.3.19]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.19.jar:5.3.19]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.19.jar:5.3.19]
... 66 common frames omitted
Caused by: java.lang.IllegalArgumentException: Can not get java.util.UUID field Parent.guid on java.lang.Long
at java.base/jdk.internal.reflect.MethodHandleFieldAccessorImpl.newGetIllegalArgumentException(MethodHandleFieldAccessorImpl.java:86) ~[na:na]
at java.base/jdk.internal.reflect.MethodHandleObjectFieldAccessorImpl.get(MethodHandleObjectFieldAccessorImpl.java:61) ~[na:na]
at java.base/java.lang.reflect.Field.get(Field.java:428) ~[na:na]
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:71) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
... 109 common frames omitted
P.S. third way have strange error, hibernate tries converting id field value to UUID
Upvotes: 1
Views: 68
Reputation: 1
The error you're facing in the third approach indicates a mismatch between the field types in your entity classes and the underlying database schema.
The error Can not get java.util.UUID field Parent.guid on java.lang.Long suggests that Hibernate is trying to read a UUID from a field that is actually a Long.
You've declared the id field in the ParentEntity as an Integer, but it should be of type UUID to match the database schema.
To rectify this issue:
Here's an updated snippet:
@Data
@NoArgsConstructor
@Entity
@Table(name = "Parent")
@Inheritance(strategy = InheritanceType.JOINED)
public class ParentEntity {
@Id
private UUID id; // Change type to UUID
private UUID guid;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "A")
public class AEntity {
private String someASpecificField;
@OneToOne
@JoinColumn(name = "id") // Ensure correct column name
private ParentEntity parent;
@OneToOne(mappedBy = "b")
private BEntity b;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "B")
public class BEntity {
private String someBSpecificField;
@OneToOne
@JoinColumn(name = "id") // Ensure correct column name
private ParentEntity parent;
@OneToOne(mappedBy = "b")
private AEntity a;
}
Ensure that the column names in @JoinColumn correspond correctly to the actual column names in your database tables. Additionally, the field types and relationships should align with your database schema to avoid mismatches and exceptions during data retrieval.
Upvotes: -1