12

我正在考虑使用 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();
}
4

4 回答 4

4

在上面的代码中,您似乎在字段(超类)和方法(子类)上混合了注释。Hibernate参考文档建议避免这种情况,我怀疑它可能会导致问题。根据我使用 Hibernate 的经验,注释 getter/setter 方法而不是字段更安全、更灵活,所以如果可以的话,我建议坚持这种设计。

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

希望这可以帮助。

于 2008-11-30T00:03:14.463 回答
3

在子方法中不要添加第二个 @Id 标记。

@Override // So that we can set Generated strategy
@GeneratedValue(strategy = AUTO)
public Integer getId() {
    return super.getId();
}
于 2008-12-04T08:18:40.793 回答
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并定义它。

于 2011-04-25T04:41:32.557 回答
1

如果您将注释放在 getter 而不是字段上,当您在子类中覆盖方法时,将使用放置在那里的注释而不是超类中的注释。

于 2009-01-10T05:01:45.563 回答