• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Spring MVC, JPA i relacja OneToOne

VPS Starter Arubacloud
0 głosów
343 wizyt
pytanie zadane 4 maja 2020 w Java przez scrxts Nowicjusz (150 p.)

Jestem na maksymalnych podstawach jeśli chodzi o Javę i springa i mam problem z relacją (OneToOne) przy zapisywaniu z poziomu widoku. A mianowicie nie wiem do końca, w jaki sposób powinienem zdefiniować metodę z wykorzystaniem adnotacji @PostMapping i w jaki sposób widok mam to zapisać. Wiem że gdzieś robię błąd i sam kod jest kompletnym serem szwajcarskim, ale momentami zaczynają mi opadać ręce.

Model User:

@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;
    @NotNull
    private String username;
    @NotNull
    private String password;
    @NotNull
    private String email;

    public User(){}

    public User(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Model UserDetails:

@Entity
@Table(name = "user_details")
public class UserDetails implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "userDetails_id")
    private Long udId;
    @NotNull
    private String firstName;
    @NotNull
    private String lastName;
    @NotNull
    private String adress;


    @OneToOne(cascade = CascadeType.ALL) 
    private User user;

    public UserDetails(){}

    public UserDetails(String firstName, String lastName, String adress) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.adress = adress;
    }

    public Long getUdId() {
        return udId;
    }

    public void setUdId(Long udId) {
        this.udId = udId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

RegisterController:
 

@Controller
public class RegisterController {

    private DetailsRepository detailsRepo;
    private UserRepository userRepo;

    @Autowired
    public RegisterController(DetailsRepository detailsRepo, UserRepository userRepo) {
        this.detailsRepo = detailsRepo;
        this.userRepo = userRepo;
    }

    @GetMapping("/register")
    public String registerView(Model mmodel){
        mmodel.addAttribute("user", new User());
        mmodel.addAttribute("details", new UserDetails());
        return "register";
    }


    @PostMapping("/register/save")
    public String register(@ModelAttribute User user, @ModelAttribute UserDetails userDetails){
        userRepo.save(user);
        userDetails.setUser(user);
        detailsRepo.save(userDetails);
        return "redirect:/";
    }
}

Byłbym wdzięczny za poradę.

1 odpowiedź

+1 głos
odpowiedź 4 maja 2020 przez mibdbz Gaduła (4,300 p.)
wybrane 4 maja 2020 przez scrxts
 
Najlepsza

Cześć. 

Wyjdźmy od tego czy chodzi Ci też o zapis danych do bazy z udziałem Hibernate? Jeśli tak to spróbuj tak...

W klasach modelowych dodaj @Column nad każdym z pól tak samo jak zrobiłeś nad id.

W modelu User umieść dodatkowa zmienna

@OneToOne(cascade = CascadeType.All)
@JoinColumn(name = "user_details")
private UserDetails userDetails;

Z modelu UserDetails wykasuj za to podobną konstrukcje z User user.

W kontrolerze powinno wyglądać to mniej więcej tak

 @PostMapping("/register/save")
    public String register(@ModelAttribute("user") User user, @ModelAttribute("details") UserDetails userDetails){
        user.setUserDetails(userDetails);
//i tu robisz sobie co tam chcesz.
        return "redirect:/";
    }

Jeśli nie, to wszystko o czym pisałem wyrzuć do kosza. @OneToOne to relacja tabel w bazie danych. Jest to znacznik używany przez jpa i Hibernate. Nie używaj wtedy @OneToOne ani @id ani @generatedValue. Czyli twoje modele zostają w tym momencie bez żadnych adnotacji.

Jest świetny kurs na udemy: https://www.udemy.com/course/spring-hibernate-tutorial/

Człowiek wyjaśnia tam krok po kroku wszystko co teraz robisz

komentarz 4 maja 2020 przez scrxts Nowicjusz (150 p.)
Rozwiązałeś mój problem, dzięki wielkie !
komentarz 5 maja 2020 przez mbabane Szeryf (79,280 p.)

Jeśli pole w tabeli ma taką samą nazwę jak pole w klasie to adnotacja @Column jest nadmiarowa. I umieszczenie jej w taki sposób:

@NotNull
@Column
private String firstName;

Nie ma większego sensu. Może to tylko oznaczać, że osoba pisząca nie do końca rozumie co zapisała:
https://youtu.be/UPWkpl5PL_w?t=200

komentarz 5 maja 2020 przez mibdbz Gaduła (4,300 p.)
Super. Nie wiedziałem że tak to działa. Jestem dopiero początkujacym. Zobaczyłem wystąpienie, które dodałeś w linku. Wielkie dzięki dużo się nauczyłem. Zastanawiam się tylko... jako osoba początkująca chyba łatwiej jest zrozumieć jak działa Hibernate/Jpa stosując niektóre z tych praktyk opisanych w wystąpieniu. Może rzeczywiście nie ten przykład z @Column, ale następny przykład z zapisywaniem do bazy napewno. Jeszcze raz dzięki za linka.
komentarz 5 maja 2020 przez mbabane Szeryf (79,280 p.)

Jeśli chcesz jeszcze lepiej zrozumieć ten framework to zapoznaj się z tymi wpisami:

https://vladmihalcea.com/tutorials/hibernate/

Ten gość z tego co mi się wydaje jest mega wymiataczem i specjalistą od hibernate. Wydał kompleksową książkę pod tytułem: The High-Performance Java Persistence niestety kosztuje co najmniej 200 zł.

 

A z czysto programistycznego punktu, żeby dobrze rozumieć ten framework to warto włączyć logi, w których wyświetlane są jakie faktycznie zapytania idą do bazy.

https://www.baeldung.com/sql-logging-spring-boot

Podobne pytania

0 głosów
0 odpowiedzi 140 wizyt
pytanie zadane 21 lipca 2017 w Java przez lewy Obywatel (1,260 p.)
0 głosów
1 odpowiedź 432 wizyt
pytanie zadane 19 maja 2017 w Java przez K0XM4N Gaduła (3,640 p.)
0 głosów
1 odpowiedź 225 wizyt
pytanie zadane 3 grudnia 2019 w Java przez patryczek036 Nowicjusz (210 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...