我被分配了这个任务,只是为了练习,但它变得非常长和具有挑战性,但它教会了我很多关于lambda和JPA的知识。
这是一个基本的Rest API,用于创建酒店、房间、客人、预订、客人类型、房间类型等。
我的初始问题是学习JPA关系,OneToOne、OneToMany等,单向、双向等等。
我还使用PostgreSQL,使用"sping.jpa.hibernate.ddl-auto=create-drop(or update)"
,根据需要更改,当我想为任何原因重新创建DB时。
所以我非常高兴和兴奋地使用我的新@Annotations来关联我的实体,并取回我需要的任何信息列表,遇到了多个问题,在这里读了很多问题,解决了我的问题,但现在我遇到了一个新问题,但然后开始质疑我的方法,也许我不应该把一切都留给JPA。
让我向您展示我的意思。我将保持我的类简短,只显示相关信息。
我有我的预订实体。
@Data
@Entity
@Table(name = "reservation")
public class Reservation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "guest", referencedColumnName = "id")
@JsonManagedReference
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Guest guest;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "room", referencedColumnName = "id")
private Room room;
@ManyToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
@JoinTable(name = "reservation_rooms",
joinColumns = { @JoinColumn(name = "reservation_id" )},
inverseJoinColumns = { @JoinColumn(name = "room_id") }
)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private List<ReservationRoom> roomList = new ArrayList<>();
private LocalDate start_date;
private LocalDate end_date;
private Boolean check_in;
private Boolean check_out;
public void addRoom(Room room) {
this.roomList.add(room);
}
public void removeRoom(Long id) {
Room room = this.roomList.stream().filter(g -> g.getId() == id).findFirst().orElse(null);
if (room != null) {
this.roomList.remove(room);
}
}
}
这是我的房间实体。
@Data
@Entity
@Table(name = "room")
public class Room {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
private Integer floor;
@JsonProperty("max_guests")
private Integer maxGuests;
@ManyToOne(fetch = FetchType.LAZY)
@JsonBackReference
private Hotel hotel;
@ManyToOne(fetch = FetchType.LAZY)
@JsonProperty("type")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private RoomType roomType;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Room)) {
return false;
}
return id != null && id.equals(((Room) o).getId());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
这是我的“Guest”实体。
@Data
@Entity
@Table(name = "guest")
public class Guest {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String first_name;
private String last_name;
private String email;
@ManyToOne(fetch = FetchType.LAZY)
@JsonProperty("type")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private GuestType guest_type;
@ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},
mappedBy = "guestList"
)
@JsonBackReference
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private List<Reservation> reservationList = new ArrayList<>();
public Guest(){}
public Guest(Long id) {
this.id = id;
}
public List<Reservation> getReservationList() {
return reservationList;
}
public void setReservationList(List<Reservation> reservationList) {
this.reservationList = reservationList;
}
}
起初,预订只能有1个房间,但要求已更改,现在可以有多个房间。因此,客人列表需要与预订的房间相关联,而不是直接与预订相关联。让我们先抛开JPA不考虑,每当我面临挑战时,我都会问自己“怎样用JPA处理?”然后研究如何使用JPA处理(这就是我了解@ManyToMany等注释的方法)。
我的做法是创建一个新表来将预订与房间关联(这已经在我的实体中使用JPA完成),然后添加客人ID。所以,这个新表将有一个PK,其中包括预订ID、房间ID和客人ID。非常简单,然后创建我的Reservation模型,其中包括Room的列表,而这个Room模型将包括Guest的列表。很容易。
但我不想在当前的Room实体中添加Guest的列表,因为我有一个端点和可能有几个其他函数,它们检索我的Room实体,我不想添加一个Guest的列表,因为随着时间的推移,这个列表会越来越大,并且这是您不需要传递的信息。
所以我进行了一些研究,发现我可以通过@Inheritance或@MappedSuperclass扩展我的实体,我可以创建一个Reservation_Room模型,其中包括Guest的列表,并在我的Reservation实体中添加一个Reservation_Room的列表,而不是Room的列表,我真的不知道这是否可行。
说了这么多,在我继续研究和修改代码之前,我想知道,这是否是正确的方法?或者我是否过度强制使用JPA?对此最佳的处理方式是什么?可以轻松地实现/映射具有三个ID关系的表吗?
主要目标是让我的Room实体以其当前状态暴露,但是当将Room添加到预订中时,该Room也将具有Guest的列表。我能用JPA做到这一点吗?还是应该创建一个新模型并根据需要填充信息?这并不意味着我不需要创建我的三个ID表。