2012-10-05 8 views
5

Ho un nuovo oggetto. Voglio sapere id prima di salvarlo. È possibile? O c'è un altro modo per questo? Sto usando jpa as orm e oracle come database.Come faccio a conoscere l'ID prima di salvare un oggetto in jpa

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

Ho un campo codice nella mia entità. Se l'utente non immette un valore per il campo code, desidero impostare il codice come ID dell'entità. Se persisto entità, ovviamente posso ottenere id e impostare il valore del codice come id, ma questo è un database di query aggiuntivo.

voglio fare qualcosa di simile

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

Si potrebbe evitare la @GeneratedValue, utilizzare il generatore di se stessi per ottenere il valore e impostarlo su entità "manualmente" – SJuan76

+0

I dont vuoi impostarlo manualmente sull'entità. se ottengo il prossimo valore per id da oracle e lo imposto su id di una nuova entità, è razionale? – mstzn

risposta

5

Dopo una lunga ricerca su questo, finalmente ho trovato una soluzione.

In realtà, se si utilizza generatore sequenza in JPA, di certo non è possibile ottenere id dell'entità prima del salvataggio nel database, perché la prossima id verrà assegnato dalla sequenza del database.

C'è un modo per ottenere l'id se si utilizza un generatore personalizzato , è possibile ottenere l'id prima del salvataggio.Ecco semplice implementazione:

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

Utilizzando CustomGenerator per il campo ID:

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8

Con un tipo @GeneratedValue ID non si può sapere che il valore in anticipo (prima realmente scriverlo). Tuttavia, una volta persistente il bean, il campo id verrà popolato in tale istanza di bean e sarà possibile ottenerlo senza dover eseguire una query aggiuntiva. In altre parole:

MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

Inoltre, a seconda di come la vostra EntityManager è configurato, potrebbe essere necessario anche il primo commit della transazione (manualmente) prima di poter ottenere che id.

aggiornamento come da commento

Se si vuole intercettare e fare qualcosa per l'entità prima di essere salvato e/o aggiornato, è possibile utilizzare JPA ascoltatori LifeCycle (se si sta utilizzando JPA versione 2): Handling JPA lifecycle event using listeners and callbacks .

Fondamentalmente si può fare un metodo validate() nel vostro fagioli, annotare con @PrePersist e @PreUpdate e fare la convalida in esso (se il codice è insieme vuoto per il valore di id)

Aggiornamento per secondo commento

Sì, ho onestamente pensato a questo solo ora: che se l'id è generato automaticamente, potrebbe essere popolato DOPO l'evento pre-persistente, in modo tale che quando viene eseguito il codice pre-persistenza non si sa ancora cosa sia l'id (si può notare anche che nell'esempio che si collega all'ID NON viene generato automaticamente ma impostato manualmente). Quello che puoi fare in questo caso è aggiungere un campo booleano alla tua entità (annotata con @Transient in modo che non venga mantenuta) chiamata isCodeEmpty (che è falsa di default se non specificatamente inizializzata). Quindi nel metodo annotato @PrePersist si controlla se il valore per il campo codice è vuoto e, in tal caso, impostare il valore booleano su true. Poi si refactoring il metodo setId(...) tale che (a parte l'impostazione del campo id) che controllerà questo booleana, e se è vero insieme il valore del campo codice a quella del campo ID:

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

Grazie per la risposta. Ho aggiornato la mia domanda. Puoi controllare? – mstzn

+0

Ho provato entity listener.but nel valore id prepersist è nullo.Non so perché è null.I implementa come that = http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htm hai suggerimento o idea? Grazie mille – mstzn

+1

la tua idea è eccellente ma dopo il metodo prePersist setId() non funziona. Ho fatto quello che dici. Lo debugging, ma il metodo setId non viene eseguito e il campo codice dont set.Prepersist sta funzionando. – mstzn

Problemi correlati