2012-11-28 12 views
8

Podstawowe pytanie: Dlaczego obiekty @Embedded nie są zawsze tworzone?@Wbudowany obiekt nie jest tworzony automatycznie, jeśli nie ma podstawowych typów pól danych

Interesującą obserwacją jest to, że Ebean nie tworzy instancji @Embedded, jeśli nie zawierają one podstawowych typów danych (int, boolean ...) lub nie zostały wcześniej dotknięte. Przykład:

@Entity 
public class Embedder { 
    // getNotAutoInstantiated() will return null if this field was not touched before 
    @Embedded 
    private NotAutoInstantiated notAutoInstantiated = new NotAutoInstantiated(); 
    // getAutoInstantiated() will always return an instance! 
    @Embedded 
    private AutoInstantiated autoInstantiated = new AutoInstantiated(); 
} 

@Embeddable 
public class AutoInstantiated { 
    // theKey is why this embedded object is always instantiated 
    private int theKey; 
    private String field1;  
} 

@Embeddable 
public class NotAutoInstantiated { 
    private String field2;  
} 
+0

Być może występuje problem z kolizjami nazw pól między wieloma osadzonymi obiektami. Zwykle dostawca JPA odwzorowuje pola obiektów osadzonych na kolumny w tabeli nadrzędnej. Jeśli osadzone nazwy pól działają długo, możesz skończyć z obciętymi nazwami pól w bazie danych, a zatem kolizjami w nazwach kolumn. – Zagrev

+0

Przykład może być mylący. Imiona są znacznie krótsze w moim kodzie i nie zaczynają się od tego samego prefiksu. Ale nawet w tym przykładzie pola zaczynają się od "nie" i "auto", więc obcięcie nie byłoby wielkim problemem. – allprog

+0

Właściwie to myślałem o "polu" i "polu". – Zagrev

Odpowiedz

3

Nie sądzę spec WZP jasno opisuje to, co powinno się zdarzyć, gdy właściwości danej @Embedded obiektu są wszystko zerowy, ale przynajmniej niektóre implementacje traktować obiekt z właściwościami null jako null obiektu, który to jest to, co widzisz.

To wydaje się rozsądną realizacją. Z pewnością jest to przydatne w moim kodzie (przy użyciu Hibernacji), gdzie jeśli ustawię obiekt @Embedded na wartość null, chcę, aby pozostało puste, gdy ładuję utrwaloną wersję.

W twoim przykładzie klasa AutoInstantiated nigdy nie może być uważana za pustą, ponieważ prymitywna właściwość theKey nigdy nie może być pusta.

+0

Niestety, sytuacja jest gorsza. Ebean wydaje się nie być zgodne z tym zachowaniem. Mamy dość złożony model danych, w którym automatycznie umieszczane są pola AutoEstantiated @Embedded w większości miejsc. Ale jest jedno miejsce, w którym tak się nie dzieje.Nie byliśmy w stanie znaleźć tej szczególnej cechy. Podejście "pozostawienie wartości zerowej" nie jest dla mnie najlepsze, ponieważ wymaga ponownego sprawdzenia wartości zerowej. To najgorsza praktyka w Javie. Można go łatwo uniknąć w takich przypadkach ... – allprog

3

Możesz chcieć sprawdzić:

https://hibernate.atlassian.net/browse/HHH-7610

W szczególności, od 5.1:

static final String CREATE_EMPTY_COMPOSITES_ENABLED 

Enable instantiation of composite/embedded objects when all of its 
attribute values are null. The default (and historical) behavior is that a null reference 
will be used to represent the composite when all of its attributes are null 
@since 5.1 
@see Constant Field Values 

Ustaw właściwość hibernate.create_empty_composites.enabled true i voila!

+0

Dzięki, to dobrze wiedzieć. Pytanie jest jednak związane z EBean. Hibernate jest prawdopodobnie lepszy pod wieloma względami, ale Ebean lepiej pasuje do małych projektów. – allprog

1

Po prostu uderzyłem w ten sam problem z Hibernate. Pierwotne pytanie o odpowiedź "dlaczego".

Ale mówić o rozwiązanie, po prostu użyć metody @PostLoad, tak wewnątrz klasy embedder coś takiego:

@PostLoad 
private void initData() { 
    if(notAutoInstantiated == null) { 
    notAutoInstantiated = new NotAutoInstantiated(); 
    } 
} 

Aktualizacja:

Ostrzeżenie! Górny kod działa, ale ma nieoczekiwany efekt uboczny! Jak tylko załadujesz obiekt z zerowym wskaźnikiem z bazy danych, zostanie on oznaczony jako brudny, z powodu tego kodu po załadowaniu! W moim przypadku, te efekty uboczne prowadzą do polecenia aktualizacji SQL z wątku, który powinien tylko ładować dane i godziny wyszukiwania tego błędu!

Powiązane problemy