Reputation: 11307
I have come across some Grails
code as follows:
Book.saveAll(bookList)
where bookList
is a List
of Book
domain instances. While this appears to be working fine (saving all the Book
instances) while run-app
, functional tests fail with the following error:
Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
Then I wanted to see some documentation about saveAll
and I cannot seem to be able to find any. Is there any documentation? Should this method even be used?
Upvotes: 4
Views: 5446
Reputation: 1962
Basically, saveAll doesn't flush. After using saveAll if you want your changes in the database immediately, you can get current session and flush it. It's how Hibernate works: When you call flush, it will flush the Hibernate session, persistent all data in session to the database immediately. If not using (flush:true), the data is only recorded in Hibernate session and only get persisted in database when Hibernate session is flushed. The time to flush the session is automatically determined by Hibernate to optimize the performance. There are different way of flushing, you can save all the datas and flush in the end.
def hibSession = sessionFactory.getCurrentSession()
hibSession.flush()
We faced the same problem. Tested which method is faster. The test were done with 300 items.
list.each{ Book.save(flush: true, failOnError: true) }
list.each{Book.save()};
def hibSession = sessionFactory.getCurrentSession();
hibSession.flush()
Book.saveAll(list);
def hibSession = sessionFactory.getCurrentSession();
hibSession.flush()
Upvotes: 7
Reputation: 75671
I'm not sure why that's not documented, but there are quite a few gaps in the docs :) The implementation is pretty basic though, it just loops through the list and calls save
on each. So you could convert it to your own loop and it should work in both scenarios, e.g.
for (book in bookList) {
book.save()
}
This has the advantage that you can check the errors of each in the loop, and it's more obvious that multiple things are being saved and that this should be done in a transaction.
Upvotes: 1