以编程方式处理Grails事务

Dón*_*nal 10 grails hibernate transactions grails-orm

当我需要保存一个对象列表时,每个对象都应该保存在它自己的事务中(这样如果一个失败它们都不会失败),我这样做:

List<Book> books = createSomeBooks()
books.each { book ->
  Book.withNewSession {
    Book.withTransaction {TransactionStatus status ->
      try {
        book.save(failOnError: true)
      } catch (ex) {
        status.setRollbackOnly()
      }
    }
  }
} 
Run Code Online (Sandbox Code Playgroud)

我使用Book.withNewSession是因为如果一本书无法保存并且事务被回滚,则会话将无效,这将阻止后续书籍保存.但是,这种方法存在一些问题:

  1. 这有点冗长
  2. 即使前一本书成功,也将始终为每本书创建一个新会话

有没有更好的办法?我SessionFactory遇到的一种可能性是依赖注入Hibernate 并改为执行此操作

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....?
  }
}
Run Code Online (Sandbox Code Playgroud)

小智 11

这应该这样做:

List<Book> books = createSomeBooks()
books.each { book ->
  Book.withNewTransaction {TransactionStatus status ->
    try {
      book.save(failOnError: true)
    } catch (ex) {
      status.setRollbackOnly()
    }
  }
} 
Run Code Online (Sandbox Code Playgroud)

如果您回滚,会话无效,它只是被清除.因此,任何访问从DB读取的实体的尝试都会失败,但是对尚未持久的实体的写入将会很好.但是,您确实需要使用单独的事务来阻止一个故障回滚所有内容,因此使用withNewTransaction.