【问题标题】:Hibernate and Java generics - Unable to create session factory using MappedSuperClassHibernate 和 Java 泛型 - 无法使用 MappedSuperClass 创建会话工厂
【发布时间】:2016-09-15 02:42:16
【问题描述】:

我有一些我们正在尝试扩展以允许重用代码的类,但 hibernate 没有这些类。以下是新类及其扩展:

超级语句类

@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);

}

基本语句类 - 稍后会扩展,但通过单个表继承

@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;
    }
}

审批超类

@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);
}

审批基类

@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;
    }
}

在运行单元测试时,我们得到错误:

java.lang.ExceptionInInitializerError 原因: org.hibernate.MappingException:无法确定类型: java.util.Set,在表:EXPNS_STTMNT,对于列: [org.hibernate.mapping.Column(approvals)] 在 org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:314) 在 org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292) ....

这似乎是某种映射错误,但我无法缩小范围。许多之前发布过该问题的人都遇到了问题,即他们的注释位于私有财产和吸气剂之上,即他们混合并匹配了他们的注释位置,但这里似乎并非如此。还有其他人对可能导致此问题的原因有任何建议吗?

【问题讨论】:

  • 可能是因为您在 getter/setter 方法上而不是在每个字段的顶部都有映射?
  • 应该没关系,只要我不混搭就行。 See here for more details
  • 在基本语句类中,在 getApprovals 方法中。检查注释是否显示 MappedBy="statements",但在 ExpenseApproval 类上没有称为 statements 的属性。
  • MappedBy 由 getProperty 名称完成,而不是类中的变量。有一个名为getStatement() 的属性,它映射到statement
  • 我已经更新了我的代码,并将 expenseStatement 更改为 statement 以防止混淆,因为其他人对此发表了评论,然后删除了评论。正如预期的那样,我仍然得到同样的错误。映射由 getMethod 命名约定完成,而不是底层变量

标签: java hibernate jpa persistence


【解决方案1】:

Hibernate 和它的错误消息通常很糟糕,但我设法解决了这个问题。这与集合无关,而与注释的位置有关。注释通常应该在超类而不是基类上。

所以例子是:

@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;
    }
}

然后要设置适当的列或覆盖注解的属性,可以在类命名约定之上使用@AssociationOverrides

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

}

【讨论】:

    猜你喜欢
    • 2016-04-07
    • 2016-04-03
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多