gpt4 book ai didi

java - @OneToMany 关系中 merge() 的奇怪行为

转载 作者:太空宇宙 更新时间:2023-11-04 12:32:11 25 4
gpt4 key购买 nike

两个实体之间有简单的关系

One- Reservation -> Many- Seats

实体是

@Entity
public class Reservation implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reservationId;
private String reservationDate;

private static final long serialVersionUID = 1L;

@OneToMany(mappedBy = "reservation", fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@Fetch(value = FetchMode.SUBSELECT)
private List<Seat> seats = new CopyOnWriteArrayList<Seat>();
// omitting get()s and set()s
}

@Entity
public class Seat implements Serializable {

@Id
@GeneratedValue (strategy = GenerationType.IDENTITY)
private Long seatId;
private Integer seatNumber;
private static final long serialVersionUID = 1L;

@JsonIgnore
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "reservationId")
private Reservation reservation;
// omitting get()s and set()s
}

首先,我保存预订信息,然后将座位信息保存在 Controller 中

@RequestMapping(value = "/proceed", method = RequestMethod.POST)
public String checkOut(@ModelAttribute("passenger")Passenger passenger,
@RequestParam("bus_id") String busId,
@RequestParam("seats")List<Seat> seats) {

passengerService.save(passenger);
try {
System.out.println("List size is " + seats.size());
Bus selectedBus = busService.getById(Long.valueOf(busId));

Reservation reservation = new Reservation();
reservation.setBus(selectedBus);
reservation.setPassenger(passenger);
reservation.setReservationDate(new Date().toString());
// Saving reservation info here
reservationService.save(reservation);

passenger.setReservation(reservation);
passenger.setBus(selectedBus);
passengerService.update(passenger);

for (Seat seat : seats) {
seat.setBus(selectedBus);
seat.setReservation(reservation);// Here it gives weird results see details bellow
seatService.save(seat);
}

} catch (Exception e) {
System.out.println("Error is " + e.getMessage());
System.out.println("Cause is " + e.getCause());
e.printStackTrace();
}

return "reservation";
}

在下面的代码中

for (Seat seat : seats) {               
seat.setBus(selectedBus);
seat.setReservation(reservation);
seatService.save(seat);
}

SeatService save() 是

@Override
public void save(Seat e) {
entityManager.merge(e);
}

它在预订表中保存了seats.size()倍的预订对象,这些信息在使用reservationService.save(reservation);之前保存,我发现导致此结果的行是

@JsonIgnore
@ManyToOne(cascade=CascadeType.ALL)// this line causes that weird behavior
@JoinColumn(name = "reservationId")
private Reservation reservation;

如果我删除cascade=CascadeType.ALL,我会得到

org.hibernate.PersistentObjectException: detached entity passed to persist:

我还尝试将 cascade=CascadeType.ALL 更改为 cascade=CascadeType.PERSIST,仍然得到相同的结果(即,它仍然在预订表中保存 seats.size() 倍的预订对象)。

请提供任何解决方案。

最佳答案

请不要使用合并来保存新实体。来自 here :

Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".

这意味着您的实例预留不是持久的,并且 hibernate 状态每次级联时都会自动插入它。

请尝试使用 entityManager.persist 来代替,否则你必须做这样的事情:

预订服务:

@Override
public Reservation save(Seat e) {
return entityManager.merge(e);
}

和 Controller :

@RequestMapping(value = "/proceed", method = RequestMethod.POST)
public String checkOut(...) {
...
Reservation reservation = new Reservation();
...
reservation = reservationService.save(reservation);
...
}

关于java - @OneToMany 关系中 merge() 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37741698/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com