Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

org.hibernate.PersistentObjectException: detached entity passed to persist: com.topgun.airline.domain.user.User

Tô tentando salvar um objeto Reservation no banco, no json ele recebe o id de um User que já tá cadastrado, mas ta dando esse erro:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.topgun.airline.domain.user.User

segue as classes:

@Entity
@Table(name = "tb_reservation")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Reservation {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id_reservation")
    private Long id;
    @JoinColumn(name = "id_user")
    @ManyToOne(cascade = CascadeType.ALL)
    private User user;
    @JoinColumn(name = "id_flight")
    @OneToOne
    private Flight flight;
    @Column(name = "reservation_available_seats", nullable = false, precision = 4)
    private Integer numberOfSeats;
    @JoinColumn(name = "id_payment", nullable = false)
    @JsonManagedReference
    @OneToOne(cascade = CascadeType.ALL)
    private Payment payment;
    @Column(name="reservation_date")
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime reservationDate;
    @Column(name = "reservation_active", columnDefinition = "BIT(1) DEFAULT 1")
    private Boolean active = true;

    public Reservation(ReservationDTO data) {
        this.user = new User(data.userId());
        this.flight = new Flight(data.flightId());
        this.numberOfSeats = data.numberOfSeats();
        this.payment = new Payment(data.payment());
    }

    public Reservation(ReservationUpdateDTO data){
        this.numberOfSeats = data.numberOfSeats();
    }

    public Reservation(Long reservationId) {
        this.id = reservationId;
    }

    public void deactivateReservation(){
        this.active = false;
    }

    @PrePersist
    protected void prePersist() {
        reservationDate = LocalDateTime.now();
    }
}
public record ReservationDTO(Long flightId, Long userId, Integer numberOfSeats, PaymentDTO payment) {
}
@Service
public class ReservationService {

    @Autowired
    ReservationRepository reservationRepository;

    public Reservation saveReservation(Reservation newReservation){
        return reservationRepository.save(newReservation);
    }
}
@RestController
public class ReservationController {

    @Autowired
    private ReservationService reservationService;
    @Autowired
    private UserService userService;
    @Autowired
    private FlightService flightService;
    @Transactional
    @PostMapping("/reservation")
    public ResponseEntity<Reservation> save(@RequestBody ReservationDTO data) {
        User user = userService.findUserById(data.userId());
        if (user == null) {
            throw new IllegalArgumentException("User not found");
        }
        Flight flight = flightService.findFlightById(data.flightId());
        if (flight == null) {
            throw new IllegalArgumentException("Flight not found");
        }
        Reservation reservation = new Reservation(data);
        reservation.setUser(user);
        reservation.setFlight(flight);

        Reservation savedReservation = reservationService.saveReservation(reservation);

        return ResponseEntity.ok(savedReservation);
    }
}	
@Entity(name = "User")
@Table(name = "tb_usuario")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "cd_user")
    private Long id;
    @Column(name = "nm_user", nullable = false, length = 70)
    private String name;
    @JsonManagedReference
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "cd_adress")
    private Adress adress;
    @Column(name="lg_email", nullable = false, unique = true)
    private String email;
    @Column(name="ps_password")
    private String password;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private List<Reservation> reservations;
    @Column(name = "bl_active", columnDefinition = "BIT(1) DEFAULT 1")
    private Boolean active = true;

    public User(Long userId) {
        this.id = userId;
    }
    public User(UserDTO data) {
        this.name = (data.name() != null) ? data.name() : this.name;
        this.adress = (data.adress() != null) ? new Adress(data.adress()) : this.adress;
        this.email = (data.email() != null) ? data.email() : this.email;
        this.password = (data.password() != null) ? data.password() : this.password;
    }
public record UserDTO(String name, AdressDTO adress, String email, String password) {
}

o código completo tá no github: https://github.com/trcosta97/top-gun-airline

2 respostas

Oi!

Como você recebe o id do usuário no json, precisa carregar o objeto completo do banco pelo id e setar no Reservation, antes de salvar o reservation no banco de dados.

solução!

Obs: remova o cascade do mapeamento na classe Reservation:

@JoinColumn(name = "id_user")
@ManyToOne
private User user;