简体   繁体   English

Hibernate和Java泛型 - 无法使用MappedSuperClass创建会话工厂

[英]Hibernate and Java generics - Unable to create session factory using MappedSuperClass

I have a few classes that we are attempting to extend to allow reuse of code, but hibernate is having none of it. 我有一些类,我们试图扩展以允许重用代码,但hibernate没有它。 Here are the new classes and their extensions: 以下是新类及其扩展:

Super statement class 超级语句课

@MappedSuperclass
public abstract class CoreStatement<S extends Approval>
    implements java.io.Serializable
{

    public abstract Long getId();

    public abstract void setId(Long id);

    public abstract Set<S> getApprovals();

    public abstract void setApprovals(Set<S> approvals);

}

Base statement class - This does get extended later on, but via a single table inheritance 基本语句类 - 稍后会扩展,但通过单个表继承

@Entity
@Table(name="EXPNS_STTMNT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name="CLASS_ID",
        discriminatorType = DiscriminatorType.INTEGER
)
public abstract class ExpenseStatement extends CoreStatement<ExpenseApproval>
{
    private Set<ExpenseApproval> approvals;

    @Override
    @Id
    @Column(name="ID", unique=true, nullable=false, precision=10, scale=0)
    public Long getId() {
        return this.id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }

    @Override
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statement",
        targetEntity = ExpenseApproval.class)
    public Set<ExpenseApproval> getApprovals() {
        return approvals;
    }

    public void setApprovals(Set<ExpenseApproval> approvals) {
        this.approvals = approvals;
    }
}

Approval super class 批准超级

@MappedSuperclass
public abstract class Approval<T extends CoreStatement> implements java.io.Serializable  {
    public abstract Long getId();

    public abstract void setId(Long id);
    public abstract T getStatement();

    public abstract void setStatement(T statement);
}

Approval base class 批准基类

@Entity
@Table(name="APPRVL")
public class ExpenseApproval extends Approval<ExpenseStatement>{
    private Long id;
    private ExpenseStatement statement;
    @Id
    @Column(name="ID", unique=true, nullable=false, precision=10, scale=0)
    public Long getId() {
        return this.id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }
    @Override
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="EXPENSE_STATEMENT_ID", nullable=true)
    public ExpenseStatement getStatement() {
        return statement;
    }

    @Override
    public void setStatement(ExpenseStatement statement) {
        this.statement= statement;
    }
}

When running through the UnitTests, we get the error: 通过UnitTests运行时,我们得到错误:

java.lang.ExceptionInInitializerError Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Set, at table: EXPNS_STTMNT, for columns: [org.hibernate.mapping.Column(approvals)] at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:314) at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292) .... java.lang.ExceptionInInitializerError由以下原因引起:org.hibernate.MappingException:无法确定:java.util.Set的类型,在表:EXPNS_STTMNT,对于org.hibernate的列:[org.hibernate.mapping.Column(approvals)] .mapping.SimpleValue.getType(SimpleValue.java:314)org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292)....

It appears to be a mapping error of some kind, but I can't narrow it down. 它似乎是某种映射错误,但我不能缩小范围。 Many people who have posted the issue before had the problem where their Annotations were located above the private property and also getters ie They mixed and matched their annotation placement, but this doesn't appear to be the case here. 许多之前发布过这个问题的人都有这样的问题:他们的注释位于私有财产之上,也有吸气剂,即他们混合并匹配他们的注释位置,但这似乎不是这里的情况。 Does anyone else have any suggestions on what could be causing the issue? 是否有其他人对可能导致此问题的原因有任何建议?

Hibernate and it's error messages are generally terrible, but I managed to solve this. Hibernate和它的错误消息通常很糟糕,但我设法解决了这个问题。 It was nothing to do with the set, but more the location of the annotations. 它与集合无关,但更多的是注释的位置。 The annotations should generally be on the superclass and not the base class. 注释通常应该在超类而不是基类上。

So the example would be: 所以例子是:

@MappedSuperclass
public abstract class Approval<T extends CoreStatement> implements java.io.Serializable  {

    private Long id;
    private T statement


    @Id
    @Column(name="ID", unique=true, nullable=false)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="STATEMENT_ID", nullable=true)
    public T getStatement() {
        return statement;
    }

    public void setStatement(T statement) {
        this.statement = statement;
    }
}

And then to set the appropriate column or override the attributes of the annotation, you can use @AssociationOverrides on top of the class naming convention. 然后要设置适当的列或覆盖注释的属性,可以在类命名约定之上使用@AssociationOverrides

@Entity
@Table(name="APPRVL")
@AssociationOverrides({
    @AssociationOverride(name="statement", joinColumns = @JoinColumn(name = "EXPENSE_STATEMENT_ID"))
})    
public class ExpenseApproval extends Approval<ExpenseStatement>{
    private ExpenseStatement statement;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM