如何使用接口作为超类和Spring Data JPA注释来实现单表继承?

时间:2014-10-21 11:47:44

标签: java spring hibernate jpa

我有一个接口,一个实现接口的抽象类和一些扩展抽象类的具体类。这个hirarchy描述了工作 仅在一种方法的实施方面有所不同。这是我班级的摘录:

作业

@Entity
@Table(name = "job")
@DiscriminatorColumn(name = "job_type", discriminatorType = DiscriminatorType.STRING)
public interface Job {

    @Id
    @GeneratedValue
    @Column(name = "id")
    long getId();

    void setId(final long id);

    @OneToOne
    @JoinColumn(name = "previous_job_id")
    Job getPreviousJob();

    void setPreviousJob(final Job previousJob);

    public abstract void start();

}

AbstractJob

public abstract class AbstractJob implements Job {

    private long id;

    private Job previousJob;

    @Override
    public long getId() {
        return id;
    }

    @Override
    public void setId(final long id) {
        this.id = id;
    }

    @Override
    public Job getPreviousJob() {
        return previousJob;
    }

    @Override
    public void setPreviousJob(final Job previousJob) {
        this.previousJob = previousJob;
    }

    @Override
    public String toString() {
        return "Job[id=" + id + ", previousJob=" + previousJob + "]";
    }

}

HelloWorldJob

@Entity
@Table(name = "job")
@DiscriminatorValue("hello_world")
public class HelloWorldJob extends AbstractJob {

    @Override
    public void start() {
        System.out.println("Hello, world!");
    }

}

当我尝试运行一个使用HelloWorldJob存储JpaRepository的简单程序时,我会遇到以下例外情况:

Exception in thread "main" 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 javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:975)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:752)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at App.main(App.java:19)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1225)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:119)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:853)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
    ... 14 more
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: HelloWorldJob
    at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:277)
    at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:224)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:775)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    ... 22 more

Hibernate documentation有一个关于如何使用xml-mapping执行此操作但不使用注释的示例。如何使用注释来映射它?

1 个答案:

答案 0 :(得分:0)

来自en.wikibooks.org

  

如果你在JPA中有一个公共接口,你只需要映射实现类,并且大部分都可以。一个问题是您需要使用实现类进行查询,因为 JPA不了解接口。对于JPQL,默认别名也是实现类,但您可以通过将实体的名称设置为公共接口来将其重新定义为公共接口。

JPA会忽略接口上的JPA注释。