The column name ... was not found in this ResultSet

0

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.

0

@PostConstruct to zuo :)
W czym jest ta adnotacja?

Początek posta jest zasadniczo czytelny, potem się zaczyna już trochę gorzej.

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.

Nie poleci żadne SO z powodu samego kontrolera. Nie jest to jasne, ale już serializacja do JSONa tak, da SO.

Drugie pytanie, z podstaw relacyjnych baz w sumie... co faktycznie zyskuje używając tutaj relacji między osobami czy osobami a ich postami?

Pytani mi nie wydaje się w obszarze RBD, ale "nakładki" w Javie, a to już nie to samo (znane są dyskusje i zarzuty n/t problemów mapowania obioektowo-relacyjnego). Oba paradygmaty mają głębokie róznice, i to wyłazi.
Osobiście mam taką zasadę odnośnie mapowania od strony "Rodzica"
@OneToMany
private List<Post> posts = new ArrayList<>();

Gdy ILOŚĆ slave jest umownie niewielka, oraz zdroworozsądkowa ISTOTNOŚĆ dla interpretacji mastera jest ważna oraz oczywista, daję takie mapowanie.
Czyli Pracownik->Etaty, człowiek Rodzic->Dzieci tak.
Ale Zapis księgowy - Konto już nie 1). To mapuję tylko od slave. Wydobywaniem tego obarczam repozytorium/serwis czy podobną warstwę.

Po drugie tutaj jest taka popularna klasa Person, ja bym dbał o jej uniwersalność, tzn żeby nadawała się nie tylko do modelu forum, ale i systemu handlowego. Ona ma nie zależeć od Post czy Faktura, to tamte klasy mają od niej zależeć

update
co do samego wyjątku Column Exception.
JPA może mieć sens, gdy pracujesz na normalnych legalnych (pełnych) obiektach. Column Exception nie pojawia się nigdy.
Zawsze byłe przeciwny "sieczce", czyli niby używanie JPA ale myślenie w SQLu. Ma wady obu podejść, i żadnych zalet.

  1. po pierwsze dużo, po drugie bez określenia kontekstu (np okres) pozbawione sensu
0

ad1)

https://nullpointerexception.pl/fetchmode-w-hibernate-czyli-jak-pobierac-dane/
https://nullpointerexception.pl/hibernate-i-problem-n-plus-1-zapytan/

Nie bardzo rozumiem jak to ma rozwiązać problem w którym w skrócie, mam encję która ma 10 pól, a w danym przypadku potrzebuje ich tylko 5 i gdy zamiast zrobić SELECT * robię SELECT col1, col2, col5 ?

@PostConstruct to zuo :)

W czym jest ta adnotacja?

Obok main(), to tylko tymczasowe na czas testów.

Początek posta jest zasadniczo czytelny, potem się zaczyna już trochę gorzej.

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.

Nie poleci żadne SO z powodu samego kontrolera. Nie jest to jasne, ale już serializacja do JSONa tak, da SO.

Racja.

Drugie pytanie, z podstaw relacyjnych baz w sumie... co faktycznie zyskuje używając tutaj relacji między osobami czy osobami a ich postami?

Pytani mi nie wydaje się w obszarze RBD, ale "nakładki" w Javie, a to już nie to samo (znane są dyskusje i zarzuty n/t problemów mapowania obioektowo-relacyjnego). Oba paradygmaty mają głębokie róznice, i to wyłazi.
Osobiście mam taką zasadę odnośnie mapowania od strony "Rodzica"
@OneToMany
private List<Post> posts = new ArrayList<>();

Gdy ILOŚĆ slave jest umownie niewielka, oraz zdroworozsądkowa ISTOTNOŚĆ dla interpretacji mastera jest ważna oraz oczywista, daję takie mapowanie.
Czyli Pracownik->Etaty, człowiek Rodzic->Dzieci tak.
Ale Zapis ksiegowy - Konto już nie. To mapuję tylko od slave.

Po drugie tutaj jest taka popularna klasa Person, ja bym dbał o jej uniwersalność, tzn żeby nadawała się nie tylko do modelu forum, ale i systemu handlowego. Ona ma nie zależeć od Post czy Faktura, to tamte klasy mają od niej zależeć

Czyli w skrócie, sugerujesz by Person, nie wiedział nic o postach? W przypadku kolekcji friends to trochę trudniejsze, bo to ta sama encja. Mogę ewentualnie zrobić dodatkową encję PersonFriends i w środku OneToMany

0
AngryProgrammer napisał(a):

Czyli w skrócie, sugerujesz by Person, nie wiedział nic o postach? W przypadku kolekcji friends to trochę trudniejsze, bo to ta sama encja. Mogę ewentualnie zrobić dodatkową encję PersonFriends i w środku OneToMany

jedno z dobrych rozwiązań.
Np jest rozwojowe, z czasem można określi jakiego charakteru ma przyjaźń (od "Małżonek" do "to skomplikowane")

0

Jeżeli zależy Ci na wyciąganiu tylko potrzebnych informacji przez api (pomijam kwestie związane z wyciąganiem danych z bazy itp)_ to zainteresuj się GraphQL'em w miejsce resta.

0
AnyKtokolwiek napisał(a):
AngryProgrammer napisał(a):

Czyli w skrócie, sugerujesz by Person, nie wiedział nic o postach? W przypadku kolekcji friends to trochę trudniejsze, bo to ta sama encja. Mogę ewentualnie zrobić dodatkową encję PersonFriends i w środku OneToMany

jedno z dobrych rozwiązań.
Np jest rozwojowe, z czasem można określi jakiego charakteru ma przyjaźń (od "Małżonek" do "to skomplikowane")

Wracając do mojej własnej zasady "istotności interpretacji", bardzo często będziesz pobierał Person i nie będą cię obchodzili Friends

0

Wygląda na to, że dużo prościej jednak pracowac z nosql, w przypadku MongoDB zrobiłem po prostu coś takiego

@Document(collection = "users")
@Getter
@Builder
class User {
    @Id
    private final String id;
    private final String email;
    private final String password;
    private final String firstName;
    private final String lastName;
    private final Set<String> friendIds;
}

I robię DTO na tej samej kolekcji

@Document(collection = "users")
@AllArgsConstructor
@Getter
public class UserPersonalInformation {
    private final String firstName;
    private final String lastName;
}

No i jego repo

public interface UserPersonalInfoRepository extends MongoRepository<UserPersonalInformation, String> {
    
}

I chyba przy takim rozwiązaniu zostanę ;)

0

JA BYM (jak to się lekko pisze) ... jakbym miał projekt kierujący się na myślenie SQLowe (pojedynczymi kolumnami) użył środków naturalnych do SQL-a, a mapowanie to dopiero druga instancja.

JDBI, MyBatis, JOOQ

0
AngryProgrammer napisał(a):

Wygląda na to, że dużo prościej jednak pracowac z nosql, w przypadku MongoDB zrobiłem po prostu coś takiego

Mam wrażenie, że lekarstwo nie wynika z Mongo, tylko ze zmiany orientacji patrzenia na maping.
Fizyczna baza ma w twoim odkryciu najmniej do tego

a ten niskopoziomowy Set<> ... jak kto lubi, dla mnie BRZYDKIE. Co z tego, że formalnie klasy Friend nie masz w zależnościach, jak masz zależność od niej .
koncepcyjnie. To w zasadzie niczego nie zmienia od pierwszego przykładu, a tracisz wspomaganie type-safe od języka
(W Posgresie /JPA tez mogłeś napisać Set<int> )

0

koncepcyjnie. To w zasadzie niczego nie zmienia od pierwszego przykładu, a tracisz wspomaganie type-safe od języka

Nie rozumiem, jakie wspomaganie type-safe od języka?

1
AngryProgrammer napisał(a):

koncepcyjnie. To w zasadzie niczego nie zmienia od pierwszego przykładu, a tracisz wspomaganie type-safe od języka

Nie rozumiem, jakie wspomaganie type-safe od języka?

Jak każde programowanie na stringach, zamiast na rzeczywistości która za tymi stringami stoi

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