【发布时间】:2017-04-09 20:54:14
【问题描述】:
我在使用 hibernate 实现 InheritanceType.JOINED 策略时遇到问题。
我总是遇到这种异常:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
... 16 common frames omitted
Caused by: org.hibernate.MappingException: Could not instantiate persister org.hibernate.persister.entity.JoinedSubclassEntityPersister
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:112) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:348) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
... 22 common frames omitted
Caused by: org.hibernate.AssertionFailure: Table school_service.abstract_person not found
at org.hibernate.persister.entity.AbstractEntityPersister.getTableId(AbstractEntityPersister.java:5118) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.persister.entity.JoinedSubclassEntityPersister.<init>(JoinedSubclassEntityPersister.java:433) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_51]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_51]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_51]
at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_51]
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
... 26 common frames omitted
我创建了一个 Spring Boot / Gradle 项目来复制这里的错误:https://github.com/tamershahin/JoinTableTest
这是主类:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "person_type")
@Table(name = "abstract_person",schema = "school_service")
@AllArgsConstructor
@NoArgsConstructor
public class Person {
@Id
@GeneratedValue()
@Column(name="person_id")
private Long id;
@Column(nullable = false, length = 125, name="name")
@Getter
@Setter
String name;
@Column(name = "person_type", nullable = false)
@Getter@Setter
String personType;
}
这是扩展它的一个:
@Entity
@DiscriminatorValue("student")
@Table(name = "student_detail",schema = "school_service")
@PrimaryKeyJoinColumn(name = "student_id", referencedColumnName = "person_id")
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Person {
@Column(length = 32, nullable = false)
@Getter
@Setter
String email;
@Column(length = 32, nullable = false)
@Getter
@Setter
String className;
}
基本上我遵循 JPA 指南,事实上,如果我切换到 InheritanceType.TABLE_PER_CLASS 策略一切正常,但我不需要这种实现。
我调试了一下这个类:.../hibernate-core-5.0.11.Final-sources.jar!/org/hibernate/persister/entity/AbstractEntityPersister.java
我注意到这段代码:
for ( int j = 0; j < tables.length; j++ ) {
if ( tableName.equalsIgnoreCase( tables[j] ) ) {
return j;
}
}
永远不会返回正确的表,因为 tableName 始终包含架构而表不包含......这就是它无法找到表的原因。
是我错误配置/滥用某些东西还是这是一个正确的错误?
谢谢各位。
T
编辑:
我正在使用这个属性:
spring.jpa.hibernate.ddl-auto=create-drop
所以数据库应该由 Hibernate 根据他的需要生成,但在它之前一切都崩溃了。
我还尝试按照此处的说明手动创建该类: http://www.javaroots.com/2013/07/hibernate-inheritance-joined-strategy.html
但没有成功。
更新: 在@crafarlo 评论之后,我开始使用 application.properties,我发现删除了这个配置:
spring.jpa.properties.hibernate.default_schema
会成功的。
这是我的完整配置:
urlwithoutschema=jdbc:mysql://localhost:3306/
spring.datasource.url=${urlwithoutschema}${spring.datasource.schema}
spring.datasource.username=school
spring.datasource.password=school
spring.datasource.schema=school_service
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.default_schema=${spring.datasource.schema}
我不明白为什么这会影响映射类表,但它确实......有什么线索吗?
【问题讨论】:
-
“@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)”与加入有什么关系?!
-
对不起,我的错:你是对的,我在这里复制粘贴的代码来自另一个使用 TABLE_PER_CLASS 的测试项目。但是github上共享的代码是正确的。我确认加入不起作用。
-
@Tamer 检查我的回复,您忘记了抽象类中的鉴别器列。单独做 Hibernate 并不是那么聪明:)
-
@cralfaro:我在使用和不使用明确声明的列的情况下进行测试,我在某处读到使用休眠自动生成不需要这样做。我正在更新 git 和 post 代码以反映在声明或不声明鉴别器列的情况下不工作的事实。不过很好:)
-
@Tamer 尝试此更改...在所有实体中添加架构,对所有表中的主键使用相同的列名,在本例中为“Person_id”只是为了简化案例跨度>
标签: java spring hibernate jpa spring-boot