我正在考虑使用Annotations来定义我的Hibernate映射但遇到了一个问题:我想使用基本实体类来定义公共字段(包括ID字段)但我希望不同的表具有不同的ID生成策略:
@MappedSuperclass
public abstract class Base implements Serializable {
@Id
@Column(name="ID", nullable = false)
private Integer id;
public Integer getId(){return id;}
public void setId(Integer id){this.id = id;}
...
}
@Entity
@Table(name="TABLE_A")
public class TableA extends Base {
// Table_A wants to set an application-defined value for ID
...
}
@Entity
@Table(name="TABLE_B")
public class TableB extends Base {
// How do I specify @GeneratedValue(strategy = AUTO) for ID here?
...
}
有没有办法做到这一点?我已经尝试将以下内容包含在TableB
中,但是hibernate反对我两次使用相同的列并且它似乎错了:
@Override // So that we can set Generated strategy
@Id
@GeneratedValue(strategy = AUTO)
public Integer getId() {
return super.getId();
}
答案 0 :(得分:4)
在上面的代码中,看起来你正在混合字段(超类)和方法(子类)上的注释。 Hibernate reference documentation建议避免这种情况,我怀疑它可能导致问题。根据我对Hibernate的体验,无论如何都要更加安全,更灵活地注释getter / setter方法而不是字段,所以如果可以,我建议坚持使用该设计。
作为问题的解决方案,我建议您完全删除Base超类中的 id 字段。而是将该字段移动到子类中,并在Base类中创建抽象的 getId()和 setId()方法。然后覆盖/实现子类中的 getId()和 setId()方法,并使用所需的生成策略注释getter。
希望这有帮助。
答案 1 :(得分:3)
关于孩子的方法,不要添加第二个@Id标签。
@Override // So that we can set Generated strategy
@GeneratedValue(strategy = AUTO)
public Integer getId() {
return super.getId();
}
答案 2 :(得分:3)
我的决议:
将Base
类重构为:
@MappedSuperclass
abstract class SuperBase<K> {
public abstract K getId();
}
@MappedSuperclass
class Base<K> extends SuperBase<K> {
@Id @GeneratedValue(AUTO)
public K getId() { ... }
}
然后,您可以从Base扩展到大多数实体类,如果需要覆盖@GeneratedValue
,只需从SuperBase
扩展并定义它。
答案 3 :(得分:1)
如果将注释放在getter而不是字段上,当重写子类中的方法时,将使用放在那里的注释而不是超类中的注释。