2

I want to set up a generic superclass that uses the generic type as the Id type in a MappedSuperClass.

Example code:

@MappedSuperClass
public class SuperClass<T> {
    @Id
    private T id;

    // add getter and setter
}

@Entity
@Table(name = "xxx")
@AttributeOverride(name = "id", column = @Column(name = "xxxColumn"))
public class entityClassA extends SuperClass<String> {
    // some more mappings + getters and setters
}

@Entity
@Table(name = "yyy")
@AttributeOverride(name = "id", column = @Column(name = "yyyColumn"))
public class entityClassB extend SuperClass<Integer> {
    // some more mappings, getters and setters
}

However, if I run this I get an exception:

T has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type

As far as I can find, this should work. I found this question that uses the exact same thing (except for the AttributeOverride): How to create a generic entity model class that supports generic id including auto generated ids?

In this question there seems to be no problem with a generic mapped Id field.

Am I doing something wrong with the AttributeOverride annotation or am I missing some other thing?

EDIT (full stack trace):

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Property SuperClass.id has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at com.ac.tms.Application.main(Application.java:25) [classes/:na]
Caused by: org.hibernate.AnnotationException: Property SuperClass.id has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type
    at org.hibernate.cfg.PropertyContainer.assertTypesAreResolvable(PropertyContainer.java:243) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.PropertyContainer.getProperties(PropertyContainer.java:233) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.addElementsOfClass(AnnotationBinder.java:1489) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:222) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:717) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 16 common frames omitted
Community
  • 1
  • 1
  • Could you add the stacktrace of the error, so we can see when it happens (and what hibernate is trying to do to get this error) ? – Thierry Apr 21 '17 at 08:09
  • Added the stack trace, hope it helps. – Arduin Cielen Apr 21 '17 at 10:18
  • Have you tried to annotate the `id` field with `@Any` (`org.hibernate.annotations.Any`) annotation ? – Thierry Apr 21 '17 at 11:48
  • Ignore my comment with the @Any annotation : i'm not able to reproduce your issue with the setup you've described : i got the sessionFactory to build (which is where it failed for you) and i was even able to get this query (with `session.get(class, id)`) : `select testentity0_.xxxColumn as xxxColum1_2_0_, testentity0_.TEST_COLUMN as TEST_COL2_2_0_ from TEST_TABLE testentity0_ where testentity0_.xxxColumn=?`, showing that the `@AttributeOverride` is working. Could you have an entity in your project that do not define the generic type ? – Thierry Apr 21 '17 at 12:13
  • @Thierry: thanks for your effort. I was looking into that, but I cannot find any class that does not define the generic type. Could it be the repository bean creation is the problem? I've created one that has 2 generic types (one for the id field and one for the result type so I can reuse it for all underlying classes)? – Arduin Cielen Apr 24 '17 at 07:58
  • This is how the generic repo looks: public interface SuperRepository extends JpaRepository, Serializable { T findById(U id); } – Arduin Cielen Apr 24 '17 at 07:59
  • After double checking all classes (again) I have indeed found 1 without the generic class filled in. But now I get another exception that looks more like a problem with the repo (see next comment for stacktrace). – Arduin Cielen Apr 24 '17 at 08:10
  • UnsatisfiedDependencyException: Error creating bean with name 'loadData' defined in Application: parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'superRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object ... at Application.main(Application.java:25) [classes/:na] Definition: `@Bean public CommandLineRunner loadData(SuperRepository superRepo) { return (args) -> { superRepo.findAll(); }; }` – Arduin Cielen Apr 24 '17 at 08:29
  • It is a bit hard to read a stacktrace in a comment. I advise you to open a new question with this new stacktrace and a code snippet of where it happens. I'll create an answer based on my comment, so that we can show that this problem is solved ;) – Thierry Apr 24 '17 at 11:40

1 Answers1

1

i'm not able to reproduce your issue with the setup you've described :

i got the sessionFactory to build (which is where it failed for you) and i was even able to get this query (with session.get(class, id)) :

select testentity0_.xxxColumn as xxxColum1_2_0_, testentity0_.TEST_COLUMN as TEST_COL2_2_0_
from TEST_TABLE testentity0_
where testentity0_.xxxColumn=?

showing that the @AttributeOverride is working. Could you have an entity in your project that do not define the generic type ?

Thierry
  • 5,270
  • 33
  • 39
  • There was indeed an entity that did not fill in the generic type. Thank you very much for your efforts! – Arduin Cielen Apr 25 '17 at 11:57
  • As a sidenote: my repository was also not correctly configured, because of type erasure, at runtime I got the error message that Object was not an Entity. But I fixed it now. Thanks again! – Arduin Cielen Apr 25 '17 at 12:02