Java 当使用联合继承策略时,SpringJPA处理多级继承的方式是否存在限制?
我正在使用PostgreSQL数据库处理Spring启动应用程序。我在使用带有多级继承的JPA2.1时遇到了一些问题 我试图理解我是在做不受支持的事情,还是在做错事 为了说明这一点,我使用连接继承策略将一个基本的三级继承结构组合在一起,如下所示: A类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
@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> { }
总之,我想知道:
(请注意,我考虑过@MappedSuperclass,但它不适合我的需要。)首先让我声明:“它应该可以工作”:错误是:“错误:column classb0_389;.dtype不存在”--您检查过您的数据库表和列是否正确吗?此外,JPA只是一个规范。您正在使用哪个实现?冬眠?日食?还有别的吗?是您生成了架构还是让引擎为您生成的?@JB Nizet:根据stacktrace
HibernateJpaDialect
Hibernate@Ralph现在我觉得自己很愚蠢。我不知怎的错过了堆栈跟踪。@拉尔夫:是的,我检查了数据库列,它们都是正确的。