Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当使用联合继承策略时,SpringJPA处理多级继承的方式是否存在限制?_Java_Spring_Postgresql_Jpa_Inheritance - Fatal编程技术网

Java 当使用联合继承策略时,SpringJPA处理多级继承的方式是否存在限制?

Java 当使用联合继承策略时,SpringJPA处理多级继承的方式是否存在限制?,java,spring,postgresql,jpa,inheritance,Java,Spring,Postgresql,Jpa,Inheritance,我正在使用PostgreSQL数据库处理Spring启动应用程序。我在使用带有多级继承的JPA2.1时遇到了一些问题 我试图理解我是在做不受支持的事情,还是在做错事 为了说明这一点,我使用连接继承策略将一个基本的三级继承结构组合在一起,如下所示: A类 @Entity @Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(name="dtype") public class ClassA { @Id

我正在使用PostgreSQL数据库处理Spring启动应用程序。我在使用带有多级继承的JPA2.1时遇到了一些问题

我试图理解我是在做不受支持的事情,还是在做错事

为了说明这一点,我使用连接继承策略将一个基本的三级继承结构组合在一起,如下所示:

A类

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="dtype")
public class ClassA {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}
B类

@Entity
@DiscriminatorValue("B")
public class ClassB extends ClassA {

    private String fieldInB;

    public String getFieldInB() {
        return fieldInB;
    }

    public void setFieldInB(String fieldInB) {
        this.fieldInB = fieldInB;
    }
}
C类

@Entity
@DiscriminatorValue("C")
public class ClassC extends ClassB {

    private String fieldInC;

    public String getFieldInC() {
        return fieldInC;
    }

    public void setFieldInC(String fieldInC) {
        this.fieldInC = fieldInC;
    }

    @Override
    public String toString() {
        return "[id: " + getId() + "; fieldInB: " + getFieldInB() + "; fieldInC: " + getFieldInC() + "]";
    }
}
存储库都很简单:

存储库

public interface ClassARepository extends CrudRepository<ClassA, Long> { }

public interface ClassBRepository extends CrudRepository<ClassB, Long> { }

public interface ClassCRepository extends CrudRepository<ClassC, Long> { }
我从上述代码得到的输出如下:

输出

    log.info("Checking inheritance structure ...");

    // Create object
    ClassC classC = new ClassC();
    classC.setFieldInB("bbbbb");
    classC.setFieldInC("ccccc");
    classCRepository.save(classC);
    log.info("--- Saved instance of class C.");

    // Test repository for Class C
    long countC = classCRepository.count();
    log.info("--- Result of classCRepository.count(): " + countC);
    for (ClassC  c : classCRepository.findAll()) {
        log.info("--- Item returned from classCRepository.findAll(): " + c.toString());
    }

    // Test repository for Class A
    long countA = classARepository.count();
    log.info("--- Result of classARepository.count(): " + countA);
    for (ClassA  a : classARepository.findAll()) {
        log.info("--- Item returned from classARepository.findAll(): " + a.toString());
    }

    // Test repository for Class B
    long countB = classBRepository.count();
    log.info("--- Result of classBRepository.count(): " + countB);
    for (ClassB  b : classBRepository.findAll()) {
        log.info("--- Item returned from classBRepository.findAll(): " + b.toString());
    }

    log.info("Inheritance structure check complete.");
Checking inheritance structure ...
--- Saved instance of class C.
--- Result of classCRepository.count(): 1
--- Item returned from classCRepository.findAll(): [id: 10; fieldInB: bbbbb; fieldInC: ccccc]
--- Result of classARepository.count(): 1
--- Item returned from classARepository.findAll(): [id: 10; fieldInB: bbbbb; fieldInC: ccccc]
--- Result of classBRepository.count(): 1
SQL Error: 0, SQLState: 42703
ERROR: column classb0_.dtype does not exist
从输出中可以看到,我可以成功地从根类(ClassA)的存储库或继承结构另一端的存储库(ClassC)检索对象,但是当我尝试使用中间类(ClassB)的存储库时,会引发异常

似乎有些组件希望ClassB的数据库表具有鉴别器列,而只有ClassA的表需要鉴别器列。(为了完整起见,将@DiscriminatorColumn注释添加到ClassB中没有任何作用。)

实际的异常堆栈跟踪(为了简洁起见减少)如下所示:

例外情况

org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:242) ~[spring-orm-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) ~[spring-orm-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) ~[spring-orm-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:
    ...
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
Caused by: org.postgresql.util.PSQLException: ERROR: column classb0_.dtype does not exist
  Position: 106
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:645) ~[postgresql-9.4-1206-jdbc42.jar:9.4]
    ...
所有这些都有一点让人费解的是,如果我只改变了继承策略,并使用单表或表/类运行相同的代码,那么代码就可以完美地运行

我花了相当长的时间阅读了所有关于这方面的文档(从Spring到PostgreSQL再到JPA2.1规范),但到目前为止运气不佳

问题

public interface ClassARepository extends CrudRepository<ClassA, Long> { }

public interface ClassBRepository extends CrudRepository<ClassB, Long> { }

public interface ClassCRepository extends CrudRepository<ClassC, Long> { }
总之,我想知道:

  • 这是JPA2.1的正常记录行为吗(如果是,请告诉我记录的位置)
  • 对于JPA2.1来说,这是正常但未记录的行为吗
  • 有什么我做错了吗
  • Spring JPA实现有什么问题吗
  • 是否有一种替代的解决方法允许我仍然使用多级继承和联合策略

  • (请注意,我考虑过@MappedSuperclass,但它不适合我的需要。)

    首先让我声明:“它应该可以工作”:错误是:“错误:column classb0_389;.dtype不存在”--您检查过您的数据库表和列是否正确吗?此外,JPA只是一个规范。您正在使用哪个实现?冬眠?日食?还有别的吗?是您生成了架构还是让引擎为您生成的?@JB Nizet:根据stacktrace
    HibernateJpaDialect
    Hibernate@Ralph现在我觉得自己很愚蠢。我不知怎的错过了堆栈跟踪。@拉尔夫:是的,我检查了数据库列,它们都是正确的。