2017-01-31 20 views
12

Mam podmiot, który jest właścicielem innego podmiotu:Jak wysłać podzbiór jednostki JPA, która jest własnością innej jednostki?

//psuedocode  
public class ClassA{ 
    private String name; 

    @OneToOne 
    private ClassB classb; 
} 

public class ClassB{ 
    private String thing1; 
    private String thing2; 
    private String thing3; 
} 

Kiedy pobierać obiekty ClassA, nie chcę, aby zobaczyć ClassB.thing3, ale chcę zobaczyć thing1 i rzeczy 2:

{ 
"name":"classa", 
"classb":{ 
     "thing1":"hi", 
     "thing2":"there" 
     } 
} 

Ale jeśli zapytać o ClassB chcę zobaczyć wszystko:

{"thing1":"hi", 
"thing2":"there", 
"thing3":"joseph"} 

Więc nie mogę po prostu położyć ignorować adnotacji nad thing3, bo wtedy będę ignorować go na SECO i pobierz. Próbowałem Converter<ClassB>, ale to zmusza mnie do wdrożenia toString() i fromString() dla JSON, który umiera na konwersję obiektu JSON na stronę Java (konwerter oczekuje String, ale dostaje obiekt zamiast).

Chcę uniknąć budowania/parsowania obiektu JSON, jeśli to możliwe, aby mój dostawca json wykonał pracę, jeśli to możliwe. Jestem w Johnzon.

+1

Jaki jest Twój dostawca json? Jackson obsługuje widoki Json, które mogą robić, co chcesz, ale są niestandardowe. Ex: http://www.baeldung.com/jackson-json-view-annotation – Gimby

Odpowiedz

1

Jest to możliwe, trzeba użyć @NamedEntityGraph,

To powinno pomóc, http://www.thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/

+0

Myślę, że aby to przyjąć jako odpowiedź, powinieneś przynajmniej opisać implementację przypadku OP, a nie tylko wskazać ogólny samouczek . – Deltharis

+0

dzięki, zrobi! był w pośpiechu @Deltharis – zillani

+0

Nie jestem pewien, czy @ NamedEntityGraph są sposobem, aby przejść tutaj, ponieważ [JPA 2.1] (http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-spec/index. html) Spec umożliwia dostawcom pobieranie tak dużej ilości danych, jakie uzna za stosowne, więc nie ma gwarancji ClassB.thing3 nie zostanie załadowany, tylko dlatego, że nie znajduje się na wykresie jednostki: _ Dostawca utrwalania może pobrać stan dodatkowej jednostki poza określony przez wykres pobierania lub wykres obciążenia. Wymagane jest jednak, aby dostawca utrwalania pobierał cały stan określony przez pobrany lub załadowany wykres._ – tom

1

Coś jak to powinno być możliwe przy użyciu kwerend wybrać nowe, ale będziesz potrzebować kilka nowych klas za to ... i nie przekazuje swoich podmiotów bezpośrednio do JSON.

nowych klas: (pseudokod)

class ResultB { 
    String thing1; 
    String thing2; 

    public ResultB(ClassB classB) { 
     this.thing1 = classB.thing1; 
     this.thing2 = classB.thing2; 
    } 
} 

class ResultA { 
    String name; 
    ResultB resultB; 

    public ResultA(ClassA classA) { 
     this.name=classA.name; 
     this.resultB=new ResultB(classA); 
    } 
} 

zapytania:

select new ResultA(a) from ClassA a fetch join a.classB; 

Następnie można przekazać ResultA zamiast ClassA do JSON.

PS: Jak wspomniano w komentarzu powyżej, nie sądzę NamedEntityGraphs są do zrobienia tutaj

+0

To może być jedno rozwiązanie, ale zamiast przekazywać ResultA do mojego dostawcy Json, byłbym skłonny przekształcić go z powrotem w ClassA i ClassB, tak aby interfejs do interfejsu frontowego mojego zespołu pozostał taki sam. Przynosi to korzyści polegające na tym, że nie trzeba wydawać zasobów na pobieranie niepotrzebnych pól, ale pochodzi z całej "potrzeby specjalnych klas dostępu do danych", które będę musiał przeprowadzić przez mój zespół, ponieważ jest to niezgodne z naszym aktualnym standardem używania podmioty jako nasze klasy transferu danych i dostępu. – GuitarStrum

+0

Hmm, tak, możesz przekonwertować to z powrotem do oryginalnych klas, jednak powinieneś uważać, że te klasy nie są uparte "tak jak są", gdy są zwracane, ponieważ możesz kasować (puste) pola (lub tworząc wyjątki, jeśli pola nie są null). – tom

1

ja zawsze pobrać wszystkie dane z bazy danych i niech filtrowanie być wykonane przez dostawcę JSON jeśli mimo wszystko chcesz serializować. Jeśli używasz Jacksona można po prostu dodać widoki na polach:

public class ClassA { 

    @JsonView(Views.AlwaysInclude.class) 
    private String name; 

    @JsonView(Views.AlwaysInclude.class) 
    @OneToOne 
    private ClassB classb; 
} 

public class ClassB { 
    @JsonView(Views.AlwaysInclude.class) 
    private String thing1; 

    @JsonView(Views.AlwaysInclude.class) 
    private String thing2; 

    private String thing3; 
} 

public class Views { 
    public static class AlwaysInclude { 
    } 
} 

Później podczas serializacji swój przedmiot wystarczy użyć widoku:

String result = mapper 
    .writerWithView(Views.AlwaysInclude.class) 
    .writeValueAsString(new ClassA()); 

Gdy chcesz serializacji tylko ClassB wtedy nie powinien używać widoków.

String result = mapper.writeValueAsString(new ClassB()); 
+0

Nie używamy Jacksona, ale dziękuję. Dla "zawsze pobierałbym wszystkie dane z bazy danych i pozwoliłbym filtrowanie do wykonania przez dostawcę JSON" komentuję, mogę iść na podobnej trasie i po prostu zerować pola, których nie potrzebuję z klasy B podczas pobierania klasy A. Wadą tego podejścia jest to, że nadal wydajemy zasoby, które pobierają dane, których nie potrzebuję, ale z drugiej strony mogę pozwolić, aby mój dostawca zbudował dla mnie prawidłowy json. – GuitarStrum