Mam tu do czynienia z przegraną i być może jest to coś oczywistego, ponieważ moja wiedza na temat Hibernacji jest słabsza niż w innych dziedzinach.Hibernuj zamień klasę embeddable na migrację istniejących danych
W starszym kodzie występuje klasa Hibernate @Entity
klasa Foo
. Jedną z jego właściwości to:
private OldBar bar = new OldBar();
OldBar
jest klasa @Embeddable
który wykorzystuje pojedynczą kolumnę, 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;
}
}
Oryginalny problemem jest to, że muszę coś zrobić z OldBar.fooBar
, ale oryginalny projekt miał ograniczenia i miał to pole prywatne, co uniemożliwiło mi jego podklasowanie, więc musiałem stworzyć całą inną klasę, NewBar
, aby zastąpić drugą klasę i uzyskać dostęp do prywatnego pola. Pomyślałem, że skoro NewBar
jest również Embeddable
i ma taką samą @Column
oznaczenie, może po prostu zamienić na pole w klasie Foo
:
private NewBar bar = new NewBar();
chciałem tego robić, bo mam istniejących danych w kolumnie foobar
i Chciałem użyć tych danych w przejrzysty sposób, używając NewBar
zamiast OldBar
.
Dzięki dziennikom śledzenia widziałem, że Foo()
jest tworzony z domyślną wersją NewBar()
, jak można się spodziewać, po wywołaniu konstruktora. Jednak do czasu kod Foo.getBar()
, z jakiegoś powodu bar
jest null
! Przypuszczam, że Hibernate ustawia z jakiegoś powodu na null
- ale dlaczego nie jest w stanie hibernacji czytając dane z kolumny foobar
i tworząc instancję NewBar
? Dlaczego znowu działa, gdy ponownie wstawiam OldBar
zamiast ? Z pewnością w bazie danych nie ma informacji, która z klas @Embeddable
jest odwzorowana na kolumnę, czy istnieje?
Aktualizacja: To staje się coraz bardziej nieznajoma. Czasami zostawiam kod na noc, a następnego dnia działa! Lub następnego dnia to nie działa! Właśnie teraz to nie zadziałało (to znaczy, właściwość foobar
została ustawiona na null
zamiast wartości w bazie danych), więc utworzyłem klasę ExactCopyOfOldBar
i ustawiłem ją na miejsce OldBar
. Wszystko działało dobrze! Wracam więc do NewBar
--- tylko cofam moje tymczasowe zmiany. Nadal działało, kiedy jeszcze nie było! Czy jest jakaś pamięć podręczna, w której Hibernate serializuje wartości i nie pobiera ich z bazy danych? To bardzo dziwne.
Aktualizacja: Teraz nie mogę już uzyskać NewBar
do pracy w ogóle. Tworzę OtherBar
, która jest w zasadzie identyczna z NewBar
, z tą różnicą, że ma inną nazwę, a ja podłączam ją i działa, poprawnie odczytując osadzony ciąg. Wracam na numer NewBar
i ponownie otrzymuję numer null
. Co się dzieje?
Należy zauważyć, że Foo
jest ładowany przez net.databinder.auth.hib.AuthDataApplication.getUser(String username)
, który jest prosty:
return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
.add(Restrictions.eq("username", username)).uniqueResult();
I zostały zweryfikowane przez cały czas, że (użytkownik) Tabela Foo
ma jeden wiersz z odpowiednich danych i co najważniejsze, że pole foobar
ma dane. Dlaczego funkcja Hibernate przesyła mi Foo
z polem null
foobar
? Dlaczego po prostu przełączenie z NewBar
na OtherBar
powoduje, że zaczyna działać ponownie? Dlaczego to działa przez cały dzień, a potem przestaje działać po tym, jak zostawiłem go na noc?
Zakładam, że to prawda, ale nie powiedziałeś tego: Czy 'Foo.bar' jest oznaczony jako' @ Embedded'? –
@Tim Pote: Rzeczywiście, o dziwo, w oryginalnym (działającym) starszym kodzie, nie było _ oznaczone jako "@ Embedded". Próbowałem go z i bez '@ Embedded', kiedy zmieniłem z' OldBar' na 'NewBar', i to nie miało znaczenia. –
@ Tim Pote: Nauczyłem się z Hibernate [dokumentacja] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/), że "... jeśli typ właściwości jest oznaczony jako @Embeddable, jest mapowany jako @Embedded, "więc technicznie część' @ Embedded' jest opcjonalna. –