0

当我尝试从属于 Ticket 类的集合中删除 TicketLine 对象并且 TicketLine 与类 Reservation 具有 OneToOne 关联时,我遇到了“已删除的对象将被级联重新保存”的问题。

Tickets 定义了一个带有以下 getter 的 TicketLines 集合

class Tickets
...
@OneToMany(targetEntity = TicketLine.class, fetch = FetchType.EAGER)
@Fetch(org.hibernate.annotations.FetchMode.SUBSELECT)
@Cascade({org.hibernate.annotations.CascadeType.ALL,  
    org.hibernate.annotations.CascadeType.LOCK,
    org.hibernate.annotations.CascadeType.DELETE_ORPHAN,})
public List<TicketLine> getLines() {
return ticketlines;
}
....

类 Reservation 定义了与 TicketLines 的 OneToOne 关系,如下所示:

class Reservation 
...
@OneToOne()
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
@JoinColumn(name = "resource_id")
public TicketLine getTicketLine() {
    return ticketLine;
}

将 TicketLine 对象添加到票证并将 Reservation 对象添加到 TicketLine 对象

ticket.getLines().add(line);
session.save(ticket);

Reservation res = new Reservation();
res.setTicketLine(m_ticketline);
....
session.save(res);

按预期工作。正在创建 Reservations 中的记录,其中票证 ID 为 resource_id 字段。

当我从具有关联的 Reservation 对象的集合中删除一行时,我收到以下错误:

Save ticket failed: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [org.myapp.hibernate.TicketLine#ff8081814a45ebb5014a45ebe4540003]

仅当存在与该行关联的 Reservation 时才会出现此错误。有趣的是,在新会话中再次尝试不会引发异常,但保留不会被删除!

从 TicketLines 集合中删除一条线路可能发生在许多地方,即手动删除预订并不是一个真正的选择。我希望这可以由 Hibernate 管理,我刚刚对级联选项做错了。

请帮忙。

4

1 回答 1

1

下面的代码出现了异常。但是,现在的问题是 line.getReservation() 总是返回 null,尽管存在预订记录。

更新:添加 mappedBy 属性

@OneToOne(mappedBy="reservation")

在预订解决了最后一个问题。line.getReservation() 现在也可以了。对不起,打扰你。

第二次更新: 只要二级缓存有效,之前建议的解决方案就可以工作。重新加载对象后,NPE 再次发生。在对拥有一段关系的术语进行了一番探讨之后,我得出了以下最终可行的解决方案。

像以前一样,Tickets 类定义了 TicketLines 的集合。

类 TicketLine 定义这样的关系:

class TicketLine
...
private reservation;
...

@OneToOne(mappedBy="ticketline", cascade= CascadeType.ALL, fetch= FetchType.EAGER)
@JoinColumn(name="id", referencedColumnName="resource_id")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
public Reservation getReservation() {
    return reservation;
}
...

类 Reservation 定义了与 TicketLines 的 OneToOne 关系,如下所示:

class Reservation 
...
privat TicketLine ticketline;
...
@OneToOne(fetch= FetchType.EAGER)
@JoinColumn(name = "resource_id", insertable=false, updatable=false)
public TicketLine getTicketline() {
    return ticketline;
}
...

也许我需要解释一下,我已将字段命名为 resource_id,以便将来它也可以用于其他类型的一对一关系。但这暂时不应该起作用。

现在将 TicketLine 对象添加到票证并将 Reservation 对象添加到 TicketLine 对象:

ticket.getLines().add(line);
session.save(ticket);

Reservation res = new Reservation();
/* set property values */
/* line might not yet have an id at that pit of time, but we need one! */
sesssion.save(line);
/* Instead of explicitly setting resource_id I tried to call 
   res.setTicketline(line);
   but this will not set the resource_id as I expected
*/
res.setResource_id(line.getId());
m_ticketline.setReservation(res);
....
/* session.save(res);  
   res is now saved when the ticket containing the line will be saved later*/
....
session.save(ticket);

保存该行并删除一行

ticket.getLines().remove(line);
session.save(ticket);

或删除票证的所有行(和预订)以及票证

session.delete(票);

一切都按预期工作。

我为许多变化道歉,但这对我来说很难解决,我想提供一个真正有效的答案。

谢谢你。

于 2014-12-14T15:06:23.857 回答