2008-11-29 72 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