2008-11-29 63 views
12

我正在考虑使用Annotations来定义我的Hibernate映射,但遇到了一个问题:我想使用基本实体类来定义公共字段(包括ID字段),但我希望不同的表具有不同的ID生成策略:如何使用Hibernate/JPA批注覆盖GenerationType策略?

@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但冬眠反对我具有相同的列两次,似乎错了:

@Override // So that we can set Generated strategy 
@Id 
@GeneratedValue(strategy = AUTO) 
public Integer getId() { 
    return super.getId(); 
} 

回答

4

在上面的代码,它看起来像你的字段(父)和混合注解方法(子类)。休眠reference documentation建议避免这种情况,我怀疑它可能导致此问题。根据我对Hibernate的经验,无论如何都要注意getter/setter方法而不是字段更安全,更灵活,所以我建议如果可以的话,坚持使用该设计。

作为您的问题的解决方案,我建议从Base超类中删除id字段。相反,将该字段移到子类中,并在您的Base类中创建抽象getId()setId()方法。然后在您的子类中覆盖/实现getId()setId()方法并使用所需的生成策略对getter进行注释。

希望这会有所帮助。

3

在孩子的方法不要添加第二个@标签。

@Override // So that we can set Generated strategy 
@GeneratedValue(strategy = AUTO) 
public Integer getId() { 
    return super.getId(); 
} 
1

如果你把你的注解上,吸气,而不是现场,当你重写子类中的方法,注释放在那里将使用而不是超类的人。

2

我的决心:

重构Base类分为:

@MappedSuperclass 
abstract class SuperBase<K> { 
    public abstract K getId(); 
} 

@MappedSuperclass 
class Base<K> extends SuperBase<K> { 
    @Id @GeneratedValue(AUTO) 
    public K getId() { ... } 
} 

然后,您可以从基地扩展了大部分的实体类的,如果有需要重写@GeneratedValue,刚刚从延长SuperBase并定义它。

+1

这是一个相当优雅的做法,为我工作! – 2012-09-10 19:12:00