javaspring-boothibernatehibernate-mapping

Problems with foreign keys in Hibernate


So, I have 2 entities:
Room:

@Entity
@Table(name = "rooms")
public class Room
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String type;
    private String image;
    private double price;
    @Column(columnDefinition = "TEXT")
    private String description;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "guest_id", referencedColumnName = "id")
    private Guest guest_id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "guest_name", referencedColumnName = "name")
    private Guest guest_name;

Guest:

@Entity
@Table(name = "guests")
public class Guest
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String phone_num;
    private String email;
    private LocalDate check_in_date;
    private LocalDate check_out_date;

    @OneToOne
    @JoinColumn(name = "room_id", referencedColumnName = "id")
    private Room room_id;

As you can see in Room there are 2 foreign keys which reference id and name fields in Guest and 1 foreign key in Guest which references id field in Room.

In my controller there's a method which is supposed update an entry inside my guests table:

@PostMapping("/update/{id}")
    public String updateGuest(@PathVariable Long id, @ModelAttribute("guest") Guest guest)
    {
        Guest existingGuest = guestRepository.findById(id).get();
        existingGuest.setName(guest.getName());
        existingGuest.setPhone_num(guest.getPhone_num());
        existingGuest.setEmail(guest.getEmail());
        existingGuest.setCheck_in_date(guest.getCheck_in_date());
        existingGuest.setCheck_out_date(guest.getCheck_out_date());
   
        guestRepository.save(guest);

        return "redirect:/guests/";
    }

It worked before I had foreign keys, but since there's now a connection between fields I think I am supposed to also update fields inside rooms table. But I am honestly quite unsure how to do it.

I think I am supposed to create a method inside repository sort of like this:

@Repository
public interface RoomRepository extends JpaRepository<Room, Long>
{
    @Query("Select g From rooms g Where g.guest_id = :guestId")
    List<Room> findGuestById(@Param("guestId") String guestId);
}

Is my thinking here correct?

Massive thanks in advance!!


Solution

  • If the guest's name changes, it's crucial to ensure that the corresponding room's guest_name field is updated to maintain data consistency between the two entities. When updating the guest's information, it's important to verify that you're modifying the existing guest entity and not inadvertently creating a new guest record.

    you need to modify the controller method, to handle these considerations

    @PostMapping("/update/{id}")
    

    public String updateGuest(@PathVariable Long id, @ModelAttribute("guest") Guest guest) { Guest existingGuest = guestRepository.findById(id).orElse(null);

    if (existingGuest != null) {
        existingGuest.setName(guest.getName());
        existingGuest.setPhone_num(guest.getPhone_num());
        existingGuest.setEmail(guest.getEmail());
        existingGuest.setCheck_in_date(guest.getCheck_in_date());
        existingGuest.setCheck_out_date(guest.getCheck_out_date());
        
        // Update the room if needed
        Room room = existingGuest.getRoom_id();
        if (room != null) {
            room.setGuest_id(existingGuest);
            // You may need to update other room attributes as well, depending on your logic
            roomRepository.save(room);
        }
    
        guestRepository.save(existingGuest);
    }
    
    return "redirect:/guests/";}
    

    Create Interface RoomRepository which extends JpaRepository and create a method to find rooms by guest ID. I think this will be helpfull for you. Thank you.