回滚与Hibernate的外键关系

时间:2009-06-15 15:36:00

标签: hibernate jpa

当必须回滚外键关系但又不想抛出事务时(即仍然继续保存其他数据),Hibernate的最佳做法是什么?

如果我只是将异常传回堆栈或者不执行此回滚,那么当我尝试保存其他数据(Null或Transient Object传递给持久)时我会遇到错误,因为BookingLines已经持续存在。

我目前通过将新实体添加到地图然后在失败时从实体列表中删除它们来处理回滚,如下所示:

/* Method that will try to create an invoice but won't roll back the transaction if
 * a currency rate can't be found.
 */
public void createInvoiceFromBooking(Booking booking) {

  Invoice invoice = new Invoice();

  //Map to hold entities that I want to roll back
  Map<BookingLine, InvoiceLine> addedLines = new HashMap<BookingLine, InvoiceLine>();

  try {
    for(BookingLine bookingLine : booking.getBookingLines()) {
        InvoiceLIne invoiceLIne = new InvoiceLIne();

        //do stuff that can throw exception
        applyCurrencyRate(invoiceLine);

        bookingLine.getInvoiceLines().add(invoiceLine);
        invoice.getInvoiceLines().add(invoiceLine);

        //add to the "rollback" map
        addedLines.put(bookingLine, invoiceLine);
    }
  } catch (Exception e) {
    //remove the InvoiceLines from the related entities
    for(BookingLine bookingLine : addedLines.keySet()) {
      bookingLine.getInvoiceLines().remove(addedLines.get(bookingLine));
    }
  }

这有效,但感觉很邪恶。还有更好的方法吗?

bookingLine.clear()并不好,因为它可能有其他已保存的InvoiceLines链接到它。

感谢。

1 个答案:

答案 0 :(得分:2)

数据库的约束是根据对象的结构创建的。换句话说,如果违反约束条件,则对象关系会出现问题。例如,你有一个A指向B但没有B指向A,或者你已经指定了一些不允许空值的关系,并且有一个空值。

出于这个原因,您应该考虑不依赖约束来保持对象模型的一致性。如果实际上通过检查对象模型确保对象模型是一致的,而不是依靠数据库来执行此操作,那么它会更好,并且更不容易出错。

此外,例外情况绝不是一个好例子。例外是处理错误,它们应该是“正常”的操作路径。

出于这个原因,就你的例子而言,我建议你选择检查货币,如果不存在,则不要将数据添加到持久性商店。