@Embeddable i skrajny przypadek z ładowaniem NPE.

0

Hej, mamy sobie zwykłe zagnieżdżenie w JPA:

@Entity
class Foo {

    @Embedded
    private Bar bar;
    
    void someLogic() {
        bar.someOtherLogic();
    }
}

@Embeddable
class Bar {
    private int column1;
    private String column2;
    private boolean column3;
    
    void someOtherLogic() {
        //
    }
}

Z tego co wyczytałem, to jeśli wszystkie kolumny column1, column2, column3 będą w DB nullami to bar będzie nullem i dostaniemy NPE w metodzie someLogic().

No logiczne ..

Inicjujemy sobie zatem : private Bar bar = new Bar() no i fajnie, działa - nie dostajemy nulla.

No właśnie, niby działa, ale natknąłem się na przypadek, że jednak leci NPE o_O. I co dziwne jedna z kolumn, akurat boolowskich zawiera wartość false. Dostajemy tam NPE mimo, że inicjalizuję to pole. Co jeszcze dziwniejsze - dla innej identycznej krotki w tabeli ten bar się inicjalizuje :D Jest tylko 1 taki rekord w DB dla którego tam ten bar się zaciąga jako null.
Może wpływ na to mają jakieś inne kolumny i to są jakieś strategie ORMa związane z pamięcią czy tam wydajnością, że tam ładuje nulla?

Ktoś ma jakieś tropy ? :D

Pod spodem siedzi psql.

2

Za mało danych podałeś - kiedy ten NPE leci.
Czy przypadkiem nie blaszczysz czegoś w cyklu życia entity:

  • wywołujesz tą metodę z konstuktora,
  • z jakiegoś gettera/settera
  • w encji detached

itd.

No logiczne ..

W JPA/Hibernate logika nie ma zastosowania

0

@jarekr000000: wiedziałem że będziesz pierwszy skoro chodzi o jpa ♡

NPE leci na bar.someOtherLogic() bo bar w jednym przypadku dla jednego rekordu w db jest nullem.

Flow jest standardowy:
Kontroler, serwis, findById po Foo i wywołanie foo.someLogic()

0

Czy kolumna column1 na pewno nie jest nullem w tym rekordzie? To, że sobie inicjalizujesz pole - to akurat przy odczycie raczej nie ma znaczenia.

0

jeśli wszystkie kolumny column1, column2, column3 będą w DB nullami

Jak jest boolean a nie Boolean to może JPA(/implementacja JPA pokroju Hibernate?) nie potrafi odróżnić false od nulla? Tj. traktuje jak null wtedy.

0

Ogólnie w encjach JPA pola zmapowane na kolumny lepiej jak nie są prymitywnymi typami

0

W każdej kolumnie poza boolowską są nulle. W boolowskiej jest false. Boolean jest mały.

0

Ale int też jest mały. Skoro tak, to nie bardzo wiadomo co tam by się miało wstawić po załadowaniu encji.
Nie wiem czy to nawet zdefiniowane zachowanie. (W tym sensie czy null, który dostajesz wynika z dokumentacji, czy jest po prostu przypadkowo tak zaimplementowany w hibernate) - równie dobrze móże lecieć exception.
Skoro masz nulle w bazie to nie używaj w tych polach typów nienullowalnych.

0

@jarekr000000: spojrzałem w kod i jest tam mał← boolean, Integer oraz String.

Co nie zmienia faktu, że dlaczego dla tego jedynego przypadku bar jest nullem? A dla innych przypadków już nie?

0

To już ciekawsze. Bo tu o ile ten boolean nie jest nullem - to powinno jednak ładować tego Bar.
Może zrobisz więcej przykładów i porównasz - kiedy jest null, a kiedy normalnie. Troche mi się nie chce wierzyć, żeby dla takich samych wierszy pojawiał się różny wynik.

0

@jarekr000000:

Wiersze były te same jeśli brać pod uwagę pola/kolumny występujące w tym embeddablu. Encja ma więcej innych pól/kolumn. Może to jakieś optymalizacje JPA/Hibernate i z powodu innych wierszy tak się dzieje, że czasem tego new Bar() załaduje a czasem nie?

Testy integracyjne mi przeszły, miesiac to działało na UATach i nikt nic nie zgłaszał, a ruch był spory. Dopiero wczoraj tester to zgłosił... no nie chce być inaczej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1