User.java
package com.example.accessingdatamysql.entities;
import javax.persistence.*;
import java.util.List;
import java.util.Objects;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String firstName;
private String lastName;
private String email;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "book_id")
private Book book;
public User() {
}
Getters/Setters
@Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", book=" + book +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id) && Objects.equals(firstName, user.firstName)
&& Objects.equals(lastName, user.lastName) && Objects.equals(email, user.email);
}
@Override
public int hashCode() {
return Objects.hash(id, firstName, lastName, email);
}
}
Book.java
package com.example.accessingdatamysql.entities;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private int numberOfPages;
private String author;
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
private List<User> users = new ArrayList<>();
public Book() {
}
Getters/Setters
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", numberOfPages=" + numberOfPages +
", author='" + author + '\'' +
'}';
}
}
UserService.java
package com.example.accessingdatamysql.services;
import com.example.accessingdatamysql.entities.Book;
import com.example.accessingdatamysql.entities.User;
import com.example.accessingdatamysql.repositories.BookRepository;
import com.example.accessingdatamysql.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserService {
private final String USER_EXISTS_ERROR = "user with id %s already exists";
@Autowired
private UserRepository userRepository;
@Autowired
private BookRepository bookRepository;
public User addUser(User user) {
userRepository.findByEmail(user.getEmail()).ifPresent(param -> {
throw new IllegalStateException(String.format(USER_EXISTS_ERROR, user.getEmail()));
});
Book book = bookRepository.findByName(user.getBook().getName()).orElse(null);
if(null == book) {
book = new Book();
}
book.setName(user.getBook().getName());
book.setAuthor(user.getBook().getAuthor());
book.setNumberOfPages(user.getBook().getNumberOfPages());
user.setBook(book);
user.setFirstName(user.getFirstName());
user.setLastName(user.getLastName());
user.setEmail(user.getEmail());
return userRepository.save(user);
}
public List<User> getUsers() {
return userRepository.findAll();
}
public User getUser(Integer id) {
return userRepository.findById(id).orElseThrow(() -> new IllegalStateException("User not found"));
}
public User updateUser(Integer id, User user) {
userRepository.findById(id).orElseThrow(() -> new IllegalStateException(("")));
user.setId(id);
userRepository.save(user);
return user;
}
public void removeUser(Integer id) {
userRepository.findById(id).orElseThrow(() -> new IllegalStateException(""));
userRepository.deleteById(id);
}
}
UserController.java
package com.example.accessingdatamysql.controllers;
import com.example.accessingdatamysql.entities.User;
import com.example.accessingdatamysql.repositories.UserRepository;
import com.example.accessingdatamysql.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping(path = "/users")
public User addNewUser(@RequestBody User user) {
return userService.addUser(user);
}
@GetMapping(path = "/users")
public Iterable<User> getAllUsers() {
return userService.getUsers();
}
@GetMapping(path = "/users/{id}")
public User getUser(@PathVariable Integer id) {
return userService.getUser(id);
}
@PutMapping("/users/{id}")
public User updateUser(@RequestBody User newUser, @PathVariable Integer id) {
return userService.updateUser(id, newUser);
}
@DeleteMapping("/users/{id}")
public void deleteUserById(@PathVariable Integer id) {
userService.removeUser(id);
}
}
Error
java.lang.NullPointerException: Cannot invoke "com.example.accessingdatamysql.entities.Book.getName()" because the return value of "com.example.accessingdatamysql.entities.User.getBook()" is null
at com.example.accessingdatamysql.services.UserService.addUser(UserService.java:29) ~[classes/:na]
at com.example.accessingdatamysql.controllers.UserController.addNewUser(UserController.java:18) ~[classes/:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.60.jar:4.0.FR]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.60.jar:4.0.FR]
http://localhost:8080/users - POST
{
"firstName": "Smith",
"lastName": "Smithy",
"email": "smithy12@gmail.com",
"books": [
{
"name" : "Effective Spring",
"numberOfPages" : "366",
"author" : "John"
}
]
}
Hello, I'm working on my first CRUD application and I wanted to implement @OneToMany relationship, where each book have multiple users. I'm trying to get it working for a few days already, but with a little success. I'm not able to POST, every other mapping works fine. There's also a problem with assigning user/book to book/user. When I use GET all I get is
{
"id": 23,
"firstName": "Will",
"lastName": "Lucky",
"email": "wlucky@gmail.com",
"book": null
}
And the same is for books
{
"id": 25,
"name": "Effective Spring",
"numberOfPages": 366,
"author": "Dantes",
"users": []
}
I know that I'm doing something wrong here, but I can't figure it out and I need your help, please. I'm pretty new to Spring, so don't be too harsh on me, as I'm still in the learning process.