2013-08-17 17 views
6

Io uso Spring e Hibernate 3.2.3 4.2.3 e JDK 7.oggetto fa riferimento a un'istanza transiente non salvato: come per irrigare o restituire oggetto salvato

Ho una semplice entità:

@Entity 
public class Language { 
    @Id 
    @GeneratedValue 
    private long id; 

    @Column(nullable = false, length = 3, unique = true) 
    private String code; 
} 

I salvata un'istanza di questa entità utilizzando una classe annotata @Service con un metodo annotato @Transactional che utilizza un DAO che salva l'entità con

sessionFactory.getCurrentSession().save(object); 

Dopo che uso d la salvatiLanguage entità per la creazione EntityX, che ha utilizzato in un rapporto ManyToOne ...

lang=new Language(); 
// ... 
languageService.saveLanguage(lang); 
e=new EntityX(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

e EntityX è definito come ...

@Entity 
public class EntityX { 
    @ManyToOne 
    @JoinColumn(nullable = false) 
    private Language language; 
     // ... 
} 

ho sempre arrivare eccezione

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language 

Provo ad utilizzare alcune definizioni in cascata in EntityX " s relazione a Language come suggerito in altri post, ma non ha alcun effetto.

Se ricarico dei salvati Language entità trovando dal suo code utilizzando alcuni HQL-query, quindi tutto funziona bene, ma che è lontano dall'essere 'bello'.

Sfortunatamente il metodo save(...) di org.hibernate.Session non restituisce l'oggetto salvato.

Qualcuno ha qualche idea su come risolverlo?

risposta

5

è che si codice in un singolo metodo @Transactional?
In caso contrario, il problema può essere che, dopo qualsiasi chiamata al metodo di servizio, la transazione verrà annullata e la sessione verrà annullata. Quando si tenta di salvare un'entità, l'oggetto linguaggio non viene rilevato nella sessione e gestito come istanza temporanea e viene fornito l'errore.

Nel caso in cui il codice è sotto singola transazione hai provato un flush() prima di salvare entità per forzare negozio Hibernate Language a base di dati e assegnarle una valida @Id entifier?

Dopo tutto - IMHO - se si dispone di una dipendenza da entità e la lingua la scelta migliore è:

@ManyToOne(cascade = CascadeType.ALL) 
private Language language; 

e cambiare il codice come:

e=new EntityX(); 
Language lang = new Language(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

e non necessario persiste in due passaggi (lingua + entità); gestire il linguaggio + entità come singolo elemento

PS: il metodo save (...) (s) di org.hibernate.Session non restituisce l'oggetto salvato perché l'oggetto rimarrà lo stesso (di riferimento non lo fa modifica), solo le modifiche alle proprietà dell'oggetto (come quella contrassegnata da questo @Id, ad esempio)!

MODIFICA:
Crea un oggetto persistente (session.save() che intendo) non risulta in un inserimento/aggiornamento immediato; senza suggerimento a cascata L'aspetto Hibernate non rileva la dipendenza tra EntityX e Language e non esegue un inserimento sql di Language prima di salvare EntityX.
languageService.save (lingua) chiamata non esegue session.flush() perché ci si trova sotto lo stesso @Transactional e senza session.commit() non viene eseguito session.flush() e l'opzione migliore è che l'oggetto Language è ancora contrassegnato come transitoria.
È possibile eseguire un controllo: estrarre servizi, salvare codice (lingua entityX) e inserire tutto in singolo @Transactional e verificare se Hibernate continua a fornire un errore.
La mia migliore opzione è ancora eseguire un flush() nel mezzo o modificare la mappatura, nessun altro modo

+0

Il codice è in un unico metodo '@ Transactional'. I metodi di servizio sono anche '@ Transactional', ma non richiedono nuove transazioni, quindi suppongo che venga utilizzato quello esistente. Ho salvato la lingua per conto proprio, perché ho una entità di lingua e molte EntityX e ognuna di esse usa la stessa entità di lingua. – t777

+1

controlla la mia modifica, troppo lunga per il commento. Spero di essere chiaro, l'inglese non è la mia lingua madre, mi dispiace –

+0

Ciao @LucaBassoRicci, sto avendo lo stesso problema ma la mia tecnologia è diversa, puoi dare un'occhiata a questo ... http://stackoverflow.com/questions/28279304/errore quando il risparmio-a-oggetto-che-ha-stranieri--oggetto-riferimenti chiave-un-non salvato –

2

In primo luogo, se il campo code è la chiave primaria (o si sta almeno utilizza come ID primaria per Hibernate), specificare @Id:

@Id 
@GeneratedValue(generator="assigned") 
@Column(length = 3) 
private String code; 

Non specificando una colonna ID potrebbe essere fonte di confusione Hibernate un po; anche se non mi citano su questo.

Se save() ancora non funziona dopo che, è possibile utilizzare merge():

Language lang = new Language("XYZ"); 
lang = session.merge(lange); 
+0

Mi dispiace. Ho abbreviato troppo il mio codice. C'è un campo ID. L'ho aggiunto al codice del mio post. Ho avuto lo stesso problema quando sto usando unire invece di salvare. – t777

Problemi correlati