2013-01-17 13 views
5

Ho una classe astratta che fornisce alcune funzionalità comuni che alcune entità EJB ereditano. Uno di questi è una colonna timestamp.JPA Entity With Abstract Class Inheritance

public abstract class AbstractEntity { 

    ... 
    private long lastModified; 
    ... 

    @Column 
    public long getLastModified() { 
     return lastModified; 
    } 

    public void setLastModified(long ts) { 
     lastModified = ts; 
    } 
} 

e

@Table 
@Entity 
public class MyEntity extends AbstractEntity { 
    ... 
    private Long key; 
    private String value; 
    ... 

    @Id 
    public Long getKey() { 
     return key; 
    } 

    public void setKey(Long k) { 
     key = k; 
    } 

    @Column 
    public String getValue() { 
     return value; 
    } 

    public void setValue(String txt) { 
     value = txt; 
     setLastModified(System.currentTimeMillis()); 
    } 
} 

Il problema è che la colonna timestamp non viene aggiunta alla tabella del database. C'è qualche annotazione che deve essere aggiunta a AbstractEntity in modo che gli ultimi campi modificati vengano ereditati come una colonna?

Ho provato ad aggiungere @Entity a AbstractEntity ma ciò ha causato un'eccezione durante la distribuzione.

org.hibernate.AnnotationException: No identifier specified for entity: 
AbstractEntity 

risposta

13

Avete diverse possibilità qui.

Non hai definito una mappatura per la tua superclasse. Se si suppone che sia un tipo queryable, si dovrebbe annotare con @Entity e si sarebbe anche bisogno di un attributo @Id (questo attributo manca @Id è la ragione per l'errore hai trovato dopo l'aggiunta del @Entity annotazione)

Se non è necessario che la superclasse astratta sia un'entità interrogabile, ma vorrebbe avere gli attributi come colonne nelle tabelle delle sottoclassi, è necessario annotarla con @MappedSuperclass

Se non si annota la tua superclasse, è considerato transitorio dal fornitore e non è mappato affatto.

EDIT: Tra l'altro, non c'è bisogno di modificare il valore lastModified te stesso (ad eccezione si vuole veramente) - si può lasciare che il provider di persistenza farlo per voi ogni volta che si persiste l'entità con un callback del ciclo di vita :

@PreUpdate 
void updateModificationTimestamp() { 
lastModified = System.currentTimeMillis(); 
} 
+2

Molte grazie Kostha - l'annotazione '@ MappedSuperclass' era la soluzione che stavo cercando. – Dobbo

+0

Prego :) C'è un'altra cosa che ho notato nel tuo codice, forse lo troverai utile - vedi la modifica. – kostja

+0

Grazie ancora Kostja - la tua modifica è esattamente dove stavo andando. Come accade, devo modificare 'lastModified' come (alcuni) gli oggetti entità sono condivisi con il client e i dati vengono trasportati tramite XML e JAXB. – Dobbo

0

È necessario specificare l'annotazione @MappedSuperclass sopra della classe AbstractEntity. Significa che stai specificando che qualsiasi cosa tu abbia annotato nella classe AbstractEntity è la parte della classe in cui stai estendendo questa classe.

E si ha anche cura della tabella jdbc - nome colonna della mappatura.