Sono in perdita qui, e forse è qualcosa di ovvio perché la mia esperienza Hibernate è più debole rispetto ad altre aree.Hibernate scambia la classe incorporabile per la migrazione dei dati esistenti
Nel codice precedente è presente una classe Hibernate . Una delle sue proprietà è questo:
private OldBar bar = new OldBar();
OldBar
è una classe @Embeddable
che utilizza una singola colonna, foobar
:
@Embeddable
public class OldBar {
private String fooBar;
@Column(length = 10, nullable = false)
private String getFooBar() {
return fooBar;
}
@SuppressWarnings("unused")
private void setFooBar(String fooBar) {
this.fooBar = fooBar;
}
}
Il problema originale è che avevo bisogno di fare qualcosa con OldBar.fooBar
, ma il il design originale aveva dei limiti e aveva questo campo privato, impedendomi di sottoclassi, quindi ho dovuto creare un'intera altra classe, NewBar
, per sostituire l'altra e ottenere l'accesso al campo privato. Ho pensato che, dal momento NewBar
è anche Embeddable
e ha lo stesso @Column
designazione, ho potuto solo scambiare il campo nella classe Foo
:
private NewBar bar = new NewBar();
ho voluto fare questo perché ho i dati esistenti nella colonna foobar
, e Volevo utilizzare in modo trasparente questi dati con NewBar
anziché OldBar
.
Attraverso i log di traccia ho visto che Foo()
è stato creato, con la sua versione predefinita di NewBar()
, come ci si aspetterebbe, quando viene chiamato il costruttore. Tuttavia, dal codice temporale chiamate Foo.getBar()
, per qualche motivo bar
è null
! Suppongo che Hibernate lo stia impostando su null
per qualche motivo --- ma perché Hibernate non legge i dati dalla colonna foobar
e crea un'istanza di NewBar
? Perché torna a funzionare quando inserisco OldBar
al posto di NewBar
? Sicuramente non c'è nulla nel database stesso che dice quale delle classi @Embeddable
è mappata alla colonna, vero?
Aggiornamento: Questo diventa estraneo e sconosciuto. A volte lascio il codice durante la notte, e il giorno dopo funziona! O il giorno dopo non funziona! Proprio ora non ha funzionato (ovvero, la proprietà foobar
è stata impostata su null
anziché sul valore nel database), quindi ho creato la classe ExactCopyOfOldBar
e l'ho inserita al posto di OldBar
. Ha funzionato bene! Quindi torno a NewBar
--- semplicemente annullando le mie modifiche temporanee. Funzionava ancora, quando non aveva mai fatto prima! Esiste una sorta di cache in cui Hibernate serializza i valori e non li ottiene dal database? Questo è molto strano
Aggiornamento: Ora non riesco più a far funzionare lo NewBar
. Creo OtherBar
, che è praticamente identico a NewBar
eccetto che ha un nome diverso, e lo collego e funziona, leggendo correttamente la stringa incorporata. Ritorno a NewBar
e ottengo di nuovo null
. Cosa sta succedendo?
noti che Foo
viene caricato attraverso net.databinder.auth.hib.AuthDataApplication.getUser(String username)
, che è abbastanza semplice:
return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
.add(Restrictions.eq("username", username)).uniqueResult();
ho verificato più volte che il (utente) tabella Foo
ha una singola riga con i dati corretti, e la cosa più importante è che il campo foobar
ha dati. Perché Hibernate mi restituisce un Foo
con un campo null
foobar
? Perché il semplice passaggio da NewBar
a OtherBar
fa sì che riprenda a funzionare? Perché funziona tutto il giorno e poi smette di funzionare dopo che l'ho lasciato durante la notte?
Suppongo che sia vero, ma non lo hai detto: 'Foo.bar' è contrassegnato come' @ Embedded'? –
@Tim Pote: In realtà, abbastanza stranamente, nel codice legacy originale (funzionante), era _non_ contrassegnato come '@ Embedded'. L'ho provato con e senza '@ Embedded' quando ho cambiato forma' OldBar' in 'NewBar', e non ha fatto la differenza. –
@Tim Pote: ho imparato da Hibernate [documentazione] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/) che "... se il tipo di proprietà è annotato come @Embeddable, è mappato come @Embedded, "quindi tecnicamente la parte' @ Embedded' è opzionale. –