When I need to save a list of objects, and each object should be saved in it's own transaction (so that if one fails they don't all fail), I do it like this:
List<Book> books = createSomeBooks()
books.each { book ->
Book.withNewSession {
Book.withTransaction {TransactionStatus status ->
try {
book.save(failOnError: true)
} catch (ex) {
status.setRollbackOnly()
}
}
}
}
I use Book.withNewSession
because if one book fails to save and the transaction is rolled back, the session will be invalid which will prevent subsequent books from saving. However, there are a couple of problems with this approach:
Is there a better way? One possibility that occurred to me is to dependency-inject the Hibernate SessionFactory
and do this instead
List<Book> books = createSomeBooks()
books.each { book ->
try {
Book.withTransaction {
book.save(failOnError: true)
}
} catch (ex) {
// use the sessionFactory to create a new session, but how....?
}
}
This should do it:
List<Book> books = createSomeBooks()
books.each { book ->
Book.withNewTransaction {TransactionStatus status ->
try {
book.save(failOnError: true)
} catch (ex) {
status.setRollbackOnly()
}
}
}
The session isn't invalid if you rollback, it is just cleared. So any attempts to access entities read from the DB would fail, but writes of not-yet-persisted entities will be just fine. But, you do need to use separate transactions to keep one failure from rolling back everything, hence the withNewTransaction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With