从数据库中删除并从文件系统中删除事务?

Make delete from Database and delete from FileSystem transactional?

我有以下方法,可以从文件系统中删除图像,并从数据库中删除相应的记录。

  boolean delete(ImageItem imageItem) {
    boolean success = false
    String imageId = imageItem.id

    ...

    Path outFile = Paths.get(fileUrl)
    if (Files.deleteIfExists(outFile)) {
      log.debug "delete() - file deleted: ${fileUrl}"
      success = true
    }

    try{
      imageItem.delete(flush: true)
    } catch (Exception e) {
      log.debug "delete() - Record deleted failed: ${e}"
      success = false
    }

    return success
  }

我想让这两个删除操作都具有事务性,这意味着这两个操作要么继续进行,要么不进行。

有办法吗?

当然可以!

ImageItem.withTransaction {status ->
   try {
      imageItem.delete(flush: true)
   } catch (Exception e) {
      status.setRollbackOnly()   
      return 
   }

   Path outFile = Paths.get(fileUrl)
   try{
      if (Files.deleteIfExists(outFile)) {
        log.debug "delete() - file deleted: ${fileUrl}"
      } catch (e) {
         status.setRollbackOnly()
      }
}

首先尝试删除数据库记录(如果失败则回滚),然后删除实际文件。

https://grails.github.io/grails-doc/latest/ref/Domain%20Classes/withTransaction.html

这可以通过使用@Transactional 注释标记此方法来完成。要回滚事务,您应该抛出运行时异常。因此,通过组织您的代码并在方法末尾制作文件删除逻辑,您可以确保在出现错误时回滚这两个操作。

@Transactional
 boolean delete(ImageItem imageItem) {
    boolean success = false
    String imageId = imageItem.id

    ...

   try{
      imageItem.delete(flush: true)
    } catch (Exception e) {

    }
    Path outFile = Paths.get(fileUrl)
    //@TODO:Throw Runtime exception in case of file deletion failure
    if (Files.deleteIfExists(outFile)) {
      log.debug "delete() - file deleted: ${fileUrl}"
      success = true
    }

    return success
  }