2008-11-29 16 views
12

Estoy considerando utilizar Anotaciones para definir mis asignaciones de Hibernate pero me he encontrado con un problema: Quiero usar una clase de entidad base para definir campos comunes (incluido el campo ID) pero quiero que diferentes tablas tengan diferentes estrategias de generación de ID:¿Cómo anulo la estrategia GenerationType usando anotaciones de Hibernate/JPA?

@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? 
    ... 
} 

¿Hay alguna manera de hacer esto? He intentado que incluye lo siguiente en TableB pero Hibernate opuesto a mi tener la misma columna dos veces y me parece mal:

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

Respuesta

4

En el código anterior, parece que estás mezclando las anotaciones en los campos (superclase) y métodos (subclase). El Hibernate reference documentation recomienda evitar esto, y sospecho que podría estar causando el problema. En mi experiencia con Hibernate, es más seguro y flexible anotar métodos getter/setter en lugar de campos de todos modos, por lo que sugiero que sigas ese diseño si puedes.

Como solución a su problema, le recomiendo eliminar el campo id de su superclase base. En su lugar, mueva ese campo a las subclases y cree los métodos abstractos getId() y setId() en su clase base. Luego, anule/implemente los métodos getId() y setId() en sus subclases y anote los getters con la estrategia de generación deseada.

Espero que esto ayude.

3

En el método en el niño no agregue la segunda etiqueta @Id.

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

Si coloca sus anotaciones en el captador en lugar de campo, y se reemplaza el método en la subclase, las anotaciones colocados allí se utilizarán en lugar de los de la superclase.

2

Mi resolución:

Refactor la Base clase en:

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

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

A continuación, puede extiende desde la base para la mayoría de las clases de entidad, y si hay que anular el @GeneratedValue, simplemente se extienden desde SuperBase y defínalo.

+1

¡esa es una manera bastante elegante de hacerlo, funcionó para mí! –

Cuestiones relacionadas