What is the Hibernate best practice when having to roll back foreign key relationships, but not wanting to throw out the transaction (ie. still proceed with saving other data)?
If I just pass the exception back up the stack or don't do this rollback, then I will hit an error when I do try to save the other data (Null or Transient Object passed to persist) as the BookingLines are already persisted.
I currently handle the rollback by adding the new entities to a map and then removing them from the entity lists on failure as follows:
/* 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));
}
}
This works but feels evil. Is there a better way?
A bookingLine.clear()
is no good as it may have other already saved InvoiceLines linked to it.
Thanks.