Mam w sumie dwa pytania, jedno dotyczy samego błędu który się pojawił, a drugie designu tej encji. Zacznijmy od samego błędu, mam taką encje
@Entity
@Data
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String password;
private String firstName;
private String lastName;
@ManyToMany
private List<Person> friends = new ArrayList<>();
@OneToMany
private List<Post> posts = new ArrayList<>();
}
I taką konfigurację w application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: qwe123
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
hibernate:
ddl-auto: update
W bazie zapisuje kilka osób
@PostConstruct
public void init() {
Person adam = userRepository.save(user("adam"));
Person jan = userRepository.save(user("jan"));
Person anna = userRepository.save(user("anna"));
adam.setFriends(List.of(jan, anna));
jan.setFriends(List.of(adam));
anna.setFriends(List.of(adam));
userRepository.save(adam);
userRepository.save(jan);
userRepository.save(anna);
}
private Person user(String name) {
Person person = new Person();
person.setFirstName(name);
return person;
}
I teraz tak, oczywiście jak wypchnę findAll() bezpośrednio do controllera, to leci StackOverflow, przez ManyToMany na tych encjach. Rozwiązaniem jest zmapowanie tego na DTO. Jeżeli jednak dobrze rozumiem, to wtedy każde query do bazy które zwraca Person, zwróci również kolekcję friends oraz posts. W większości przypadków to nie ma sensu, powiedzmy, że chcę zrobić endpoint typu GET/user/profile, gdzie zwracam jego dane osobowe i tyle. Oczywiście mogę wyciągnąć z bazy wszystko i zmapować na DTO, ale to raczej słabe rozwiązanie, jeżeli np. dana osoba ma 200 przyjaciół i 1000 postów, które wyciągne tylko po to by wziąć imię i nazwisko tej osoby.
Dopisałem więcj takie coś w repo, oczekując że dostanę Person z wypełnionym tylko id, firstName, lastName.
public interface PersonRepository extends CrudRepository<Person, Long> {
@Query(
value = "SELECT p.id, p.first_name, p.last_name FROM PERSON p WHERE p.id = ?1",
nativeQuery = true)
Optional<Person> findPersonBasicInformation(Long id);
}
Wygląda jednak na to, że w tym zapytaniu muszę podać wszytkie kolumny, bo leci coś takiego i nie bardzo wiem dlaczego.
org.postgresql.util.PSQLException: The column name email was not found in this ResultSet.
Drugie pytanie, z podstaw relacyjnych baz w sumie... co faktycznie zyskuje używając tutaj relacji między osobami czy osobami a ich postami? Powiedzmy, że chcę wyciągnąć dane posta i podstawowe informację o jego autorze, jaka jest korzyść z zrobienia tutaj relacji między tymi encjami? Mógłbym chyba po prostu wywalić kolekcję posts z encji Person, a za to w encji Post trzymać tylko id autora i zrobić joina który wyciągnie mi dodatkowo np. jego imię i nazwisko.