一尘不染

以编程方式处理Grails交易

hibernate

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

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

Book.withNewSession之所以使用,是因为如果一本书无法保存并且交易被回滚,则该会话将无效,这将阻止后续书籍的保存。但是,这种方法存在两个问题:

  1. 有点冗长
  2. 即使上一本书成功,也会为每本书创建一个新的会话

有没有更好的办法?我发生的一种可能性是依赖注入Hibernate,SessionFactory然后执行此操作

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....?
  }
}

阅读 258

收藏
2020-06-20

共1个答案

一尘不染

应该这样做:

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

如果您回滚,该会话无效,它将被清除。因此,任何访问从数据库读取的实体的尝试都将失败,但是写尚未持久的实体就可以了。但是,您确实需要使用单独的事务来防止一个故障回滚所有事件,因此要避免withNewTransaction。

2020-06-20