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

标签 java hibernate spring-mvc spring-data-jpa

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

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/

相关文章:

java - 什么是 NullPointerException,我该如何解决?

java - hibernate createAlias with 子句生成错误的查询

java - 在自定义身份验证过滤器中处理 Spring Boot 上的错误

mysql - GWT Hibernate 程序 2 中的错误

java - 无法清除 hibernate 缓存

java - Spring MVC 和 UI 组件

Java 已启动但返回退出代码 13

hibernate - Open Session In View 如何与 jms 连接/ session 一起使用?

java - Jasper 报告 Excel 导出错误

java - 为什么我的loginService为空?