The booking system involves entities: User, Reservation, Course.
Problem: ReservationService doesn't add the reservation to the database nor to the user. Auto-generated long id of Reservation reservation = new Reservation(); is 0 [I tried Sequence generation type, didn't work]. Then,
reservationService.addReservation(reservation); causes an error: detached entity passed to persist.
Relationships:
User -- oneToMany --> Reservation -- oneToOne --> Course
ReservationController:
@Controller
public class ReservationController {
private final AppUserService appUserService;
private final ReservationService reservationService;
private final CourseService courseService;
public ReservationController(AppUserService appUserService, ReservationService reservationService, CourseService courseService) {
this.appUserService = appUserService;
this.reservationService = reservationService;
this.courseService = courseService;
}
@RequestMapping(value = "bookCourse/{courseId}")
public String bookCourse(@PathVariable("courseId") long id, Principal principal) {
AppUser user = appUserService.getAppUser(principal.getName());
Course course = courseService.getCourse(id);
Reservation reservation = new Reservation();
reservation.setAppUser(user);
reservation.setCourse(course);
reservationService.addReservation(reservation);
user.getReservations().add(reservation); //this line causes the error:
//org.hibernate.PersistentObjectException: detached entity passed to persist: application.domain.Course
appUserService.editAppUser(user);
return "redirect:/reservations.html";
}
Reservation Service Implementation:
@Service("reservationService")
@Transactional
public class ReservationServiceImpl implements ReservationService {
private final ReservationRepository reservationRepository;
@Autowired
public ReservationServiceImpl(ReservationRepository reservationRepository) {
this.reservationRepository = reservationRepository;
}
@Transactional
public void addReservation(Reservation reservation) {
reservationRepository.save(reservation);
};
User.java:
@Entity
@Table(name="appuser")
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
long id;
@OneToMany(mappedBy="appUser", cascade = CascadeType.ALL)
private Set<Reservation> reservations;
//getters and setters
}
Reservation.java:
@Entity
@Table(name="reservation")
public class Reservation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToOne(cascade = CascadeType.ALL)
@JsonManagedReference
private Course course;
@ManyToOne(fetch = FetchType.EAGER)//(mappedBy="reservation")
private AppUser appUser;
//getters and setters
Course.java:
@Entity
@Table(name="course")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotEmpty
private String name;
@NotEmpty
private String price;
@JsonBackReference
@OneToOne(mappedBy="course")
private Reservation reservation;
//getters and setters
In the database, an appuser_reservation junction table has been created to link the ids of a user and a reservation.
In the database, reservation has appuser_id and course_id "automatically" created, and of bigint type.
The ReservationController method is referenced by clicking in course list html:
<a href="bookCourse/${course.id}">Book!</a>
[course already is in the Database]
Framework is Spring, database is PostgreSQL.
If there are more information needed, please let me know!
Since I don't know if the issue is that new Reservation() creates a reservation with a null id, so then it can't be properly saved to DB by the service, or there is some other, more general issue, I don't know if the title of this question is appropriate.
I know the error in itself has been discussed, but I am unable to solve this issue for days now and I'll be immensely grateful for all insight. Perhaps I make an error in understanding relationships or how new Entity() works.
What is going wrong in bookCourse{id} with creating a new Reservation(); and writing it to the database?
CodePudding user response:
OK, we met in person and solved the problem.
Relationship with JPA and Hibernate were wrong.
You need to change the relationship in Reservation to be:
@Entity
@Table(name="reservation")
public class Reservation {
...
@ManyToOne
private Course course;
...
}
You have a live drawing here so you can remember what is what and what the relationship is.
auto-generated long id of Reservation reservation = new Reservation(); is 0
First you need to add created entity to database and fetch it to gets auto-generated id like this:
Reservation reservation = new Reservation();
// fill the reservation
// I assume there is repository.save(reservation);
Reservation reservationWithID = reservationService.add(reservation);
// assign reservationWithID to User Reservation List to create connection