InheritanceType.JOINED策略无法使用Spring Boot

时间:2016-11-25 12:37:00

标签: java spring hibernate jpa spring-boot

我在使用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}

我不明白为什么这会影响映射类表,但它确实有任何线索?

3 个答案:

答案 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")

AbstractEntityPersister.class:3765

因为,在这段代码中,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