Szczerze, nie widzę potrzeby tworzenia dodatkowej aplikacji server-side. Nie bardzo też rozumiem, jaki masz problem z klientem.
Skupmy się na tym problemie:
Teraz chce zrobić klienta, który pobierałby jsony z linku. Chcę mieć relację OneToMany miedzy Person (id, firstname, lastname) a Book, jedna osoba może mieć wiele książek. I później wystawić z klienta coś w stylu PersonAndBooks(id_person, firstname, lastname, bookList(id, name, publishDate). I nie wiem w sumie jak to powinno wyglądać...
Jak rozumiem potrzebujesz JSONa, który będzie miał mniej więcej taką postać:
[
{
"id": "1",
"name": "Camille Kent",
"books": [
{
"id": 1,
"author": "Valarie Mullins",
"title": "Ullamco exercitation deserunt deserunt dolore eu laborum tempor do excepteur qui."
},
{
"id": 2,
"author": "Charmaine Jensen",
"title": "Magna adipisicing irure ex laborum aliquip cillum in cupidatat anim."
}
]
}
]
Masz kilka sposobów na zbudowanie encji. Możesz automatycznie pobierać osobę i książki, możesz też pobierać tylko osoby, a ich książki tylko wtedy, kiedy potrzebujesz.
Pierwszy przypadek, kiedy zawsze zwracasz osobę z powiązanymi książkami wyglądałby tak:
@NamedQuery(name = "Person.findByPersonId", query = "SELECT p FROM Person p WHERE p. personId = :personId"),
public class Person implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "person_id")
private Integer personId;
@Column(name = "name")
private String name;
@OneToMany(targetEntity = Book.class, fetch = FetchType.EAGER)
@JoinColumn(name = "id")
private List<Book> books;
Załóżmy, że API będzie miało na przykład taką postać:
@GET
@Path("person/{id}")
@Produces({"application/xml", "application/json"})
public Response personWithBooksREST() {
//... dodaj EntityManager i obsługę błędów
Person person = em.createNamedQuery("Person.findByPersonId").setParameter("personId",1).getSingleResult();
return Response.ok(new Gson().toJson(person)).build();
}
Powyższe rozwiązanie zwróci JSONa, który będzie przedstawiał osobę i powiązane z nią książki. Musisz mieć jednak na uwadze, że kiedy będziesz chciał pobrać wszystkie osoby, aplikacja zwróci wszystkie osoby i ich powiązane książki (sam musisz ocenić, czy potrzebujesz zawsze wszystkich danych, czy potrzebujesz czasem np tylko listy osób, bez książek).
Kolejna opcja, kiedy aplikacja zwróci osobę i jej książki, ale tylko na wyraźne życzenie:
Po pierwsze mała zmiana w definicji encji:
@OneToMany(targetEntity = Book.class) //usuwamy FetchType.EAGER, teraz aplikacja użyje domyślnego ustawienia, czyli FetchType.LAZY
@JoinColumn(name = "id")
private List<Book> books;
Do tego musimy napisać odpowiednie zapytanie, które powie aplikacji, że chcemy, aby do osoby zostały dołączone książki:
@NamedQuery(name = "Person.getPersonWithBooks", query = "SELECT p FROM Person p JOIN FETCH p.books WHERE p. personId = : personId"),
Plus wywołanie w API:
Person person = em.createNamedQuery("Person.getPersonWithBooks").setParameter("personId",1).getSingleResult();
Powyższe to tylko dwa przykładowe sposoby na rozwiązanie przedstawionego problemu. JPA daje spore możliwości wystawienia danych w odpowiednim formacie, więc postaraj się udostępnić taki zakres i format danych, jaki akurat jest potrzebny.
dodanie znacznika <code class="java">
- @furious programming