Hibernate 和 Java 泛型 - 无法使用 MappedSuperClass 创建会话工厂
Hibernate and Java generics - Unable to create session factory using MappedSuperClass
我有几个 classes 我们正在尝试扩展以允许重用代码,但 hibernate 有 none 它。以下是新的 classes 及其扩展:
超级声明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);
}
基本语句 class - 这稍后会得到扩展,但通过单个 table 继承
@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;
}
}
认可超级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);
}
认可度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;
}
}
当运行通过单元测试时,我们得到错误:
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)
....
这似乎是某种映射错误,但我无法缩小范围。许多之前发布过该问题的人都遇到过他们的注释位于私有 属性 和 getters 之上的问题,即他们混合并匹配了他们的注释位置,但这里似乎不是这种情况。其他人对可能导致问题的原因有任何建议吗?
Hibernate 及其错误消息通常很糟糕,但我设法解决了这个问题。这与集合无关,而与注释的位置有关。注释通常应该在 superclass 而不是 base class.
所以这个例子是:
@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;
}
}
然后要设置适当的列或覆盖注释的属性,您可以在 class 命名约定之上使用 @AssociationOverrides
。
@Entity
@Table(name="APPRVL")
@AssociationOverrides({
@AssociationOverride(name="statement", joinColumns = @JoinColumn(name = "EXPENSE_STATEMENT_ID"))
})
public class ExpenseApproval extends Approval<ExpenseStatement>{
private ExpenseStatement statement;
}
我有几个 classes 我们正在尝试扩展以允许重用代码,但 hibernate 有 none 它。以下是新的 classes 及其扩展:
超级声明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);
}
基本语句 class - 这稍后会得到扩展,但通过单个 table 继承
@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;
}
}
认可超级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);
}
认可度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;
}
}
当运行通过单元测试时,我们得到错误:
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) ....
这似乎是某种映射错误,但我无法缩小范围。许多之前发布过该问题的人都遇到过他们的注释位于私有 属性 和 getters 之上的问题,即他们混合并匹配了他们的注释位置,但这里似乎不是这种情况。其他人对可能导致问题的原因有任何建议吗?
Hibernate 及其错误消息通常很糟糕,但我设法解决了这个问题。这与集合无关,而与注释的位置有关。注释通常应该在 superclass 而不是 base class.
所以这个例子是:
@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;
}
}
然后要设置适当的列或覆盖注释的属性,您可以在 class 命名约定之上使用 @AssociationOverrides
。
@Entity
@Table(name="APPRVL")
@AssociationOverrides({
@AssociationOverride(name="statement", joinColumns = @JoinColumn(name = "EXPENSE_STATEMENT_ID"))
})
public class ExpenseApproval extends Approval<ExpenseStatement>{
private ExpenseStatement statement;
}