我在使用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始终包含架构,而且表格没有...这就是为什么它无法找到该表格。
我是错误配置/误用某些东西还是这是一个错误的错误?
谢谢大家。
Ť
修改
我正在使用此属性:
spring.jpa.hibernate.ddl-自动=创建降
所以数据库应该由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}
我不明白为什么这会影响映射类表,但它确实有任何线索?
答案 0 :(得分:0)
未找到表school_service.abstract_person
缺少表school_service.abstract_person。 TABLE_PER_CLASS不需要这个,但是对于JOINED,您需要为层次结构中的每个实体提供一个表。
答案 1 :(得分:0)
您没有通过JOIN进行继承。你应该用这个:
@Entity
@Inheritance(strategy = InheritanceType.JOINED
@DiscriminatorColumn(name = "person_type")
@Table(name = "abstract_person",schema = "school_service")
@AllArgsConstructor
@NoArgsConstructor
public abstract class Person {
@Id
@Getter
@Setter
@Column(name = "ID")
@GeneratedValue(...)
private Integer id;
//...
@Entity
@DiscriminatorValue("student")
@Table(name = "student_detail",schema = "school_service")
@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;
}
在子类表中定义PK,与主表中的PK相同。然后联接将起作用
更新:
您也忘了在抽象类
中添加discriminator列@DiscriminatorColumn(name = "person_type", discriminatorType = DiscriminatorType.STRING)
...
@Getter @Setter
@Column(name = "person_type", nullable = false, insertable = false, updatable = false)
@Enumerated(value = EnumType.STRING)
private String type;
答案 2 :(得分:0)
删除架构=&#34; school_service&#34;来自@Table,它应该可以解决你的问题。
这
@Table(name = "abstract_person",schema = "school_service")
要
@Table(name = "abstract_person")
因为,在这段代码中,Hibernate尝试比较&#34; school_service.abstract_person&#34;用&#34; abstract_person&#34;。
public static int getTableId(String tableName, String[] tables) {
for(int j = 0; j < tables.length; ++j) {
if (tableName.equalsIgnoreCase(tables[j])) {
return j;
}
}
throw new AssertionFailure("Table " + tableName + " not found");
}
这就是您遇到此错误的原因:
未找到表school_service.abstract_person