hibernate(+spring) one to many count rows

0

witam, mam problem, a polega on na tym że nie wiem czy dobrze to robie pod względem rozplanowania itd.:
mam relacje one-to-many w bazie danych. Są ludzie i każdy człowiek ma ileś książek. (Ludzie 1) - (N Książki), i książki trzymają id ludzi.
Teraz przy pokazywaniu ludzi na stronie, chcę także pokazać ile każdy człowiek ma książek. Jakieś ogólne wskazówki jak to zrobić?
Obecnie robie to tak:

  1. w PersonService fetchuje ludzi,
List<Person> people =  personService.getPeople();
  1. potem zmieniam ludzi na PersonDTO ktore są wyposażone w pole "ilośćKsiążek", czyli
List<PersonDTO> peopleDTO= conver.convertToDto(people) [ i zmieniam wszystko na dto wyposażone w dodatkowe pole]
  1. potem robię mape i sprawiam żeby każdy z tych peopleDTO wywołał akcje repozytorium booksDao.getBooksCountForPersonId(personId) i pobrał ilośc książek dla danej osoby
query HQL wykonywane przez booksDao.getBooksCountForPersonId(personId) wygląda tak : select count(*) from Book where person_id=:person_id 
List<PersonDTO> peopleWithBooksCount = peopleDTO.stream().peek(e -> e.setBooksCount(booksDao.getBooksCountForPersonId(elm.getId()))).collect(Collectors.toList());
  1. Zwracam do kontrollera rest to dto i wysyłam json

I teraz pytanie: czy to jest w ogóle dobre rozwiązanie? najpierw pobieram całą liste, potem zmieniam ją na dto a potem jeszcze raz mapuje wszystko pobierając z serwisu dane, to tak powinno wyglądać?

0

Jest to rozwiązanie pt. czyste zło -> N+1. Totalnie słaby performance. No i w ogóle skąd w encji ( chodzi o klasę nie tabele w bazie danych) jawnie podana nazwa klucza obcego?
Pokaż mapowane encje bo coś mi się nie podoba

0

@scibi92:

@Entity
public class Person {
	
	@Id
	@GeneratedValue
	private Long id;
	
	private String name;
	[...] reszta, nieważne pola

	@OneToMany(mappedBy="personRef")
	private List<Book> bookList;

	[...] gettery/settery itd.
@Entity
public class Book {
	
	@Id
	@GeneratedValue
	private Long id;
	
	private String title;
	[...] reszta, nieważne pola

	@ManyToOne
	@JoinColumn(name="person_id")
	private Person personRef;

	[...] gettery/settery itd.

Jak inaczej to zrobić? stworzyć w Encji Person nowe pole w stylu booksCount?

0

Same encje ok, nawet nie wiedziałem że w HQL mozna pisac joiny z użyciem bezpośrednio nazwy klucza.
Cóż nowe pole to też szatański pomysł :P. Ja widze 2 rozwiązania -> albo zrobić select który jednocześnie zwróci i obiekt person i liczbę książek na tą osobę lub zrobić fetchJoin i pobrać ksiązki wraz z osobami i np. w Streama zsumować.
Ew. 3 opcja zrobić 2 selecty ->jeden tylko do osób, drugi do liczenia ksiązek na np. id osoby i później to "złączyć".

0

@scibi92:
gdzie miałbym umieścić te selecty itd? W sensie mam
Jakiś Controller - PersonService - PersonDao - Person(entity)
miałbym z PersonDao zwracać ten obiekt z selectami? bo na razie mam coś w stylu:

public List<Person>  allPersonList() 

ale to zwraca obiekt Person, czyli "dozwolone" jest żeby metoda repozytorium zwracała coś innego niż encje? Przez to co napisałeś rozumiem że chodzi o taką metode:

public List<Object> allPersonListWithBooksCount();

a potem w serwisie to wszystko konwertować? dobrze zrozumiałem?

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