Java Spring如何处理文件保存

Java Spring如何处理文件保存,java,spring,transactions,Java,Spring,Transactions,在应用程序中,我当前正在将文件保存到文件系统,然后更新数据库。我的问题是:我应该在交易中还是在交易前做 目前我是这样做的-在事务之前,如果出现保存文件失败,则不会更新数据库: @POST @Path("passport") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response saveDocument(@FormDataParam("file") InputStream uploadedInputStream,

在应用程序中,我当前正在将文件保存到文件系统,然后更新数据库。我的问题是:我应该在交易中还是在交易前做

目前我是这样做的-在事务之前,如果出现保存文件失败,则不会更新数据库:

@POST
@Path("passport")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response saveDocument(@FormDataParam("file") InputStream uploadedInputStream,
                                   @FormDataParam("file") FormDataContentDisposition fileDetail,
                                   @FormDataParam("documentTypeId") int documentTypeId,
                                   @FormDataParam("id") int id) {

    String fileName = fileDetail.getFileName();
    String result = "";
    String[] split = fileName.split("\\.");
    if (split.length == 1) {
        //No extension
        result = split[0] + new Date().getTime();
    } else {
        for (int i = 0; i < split.length - 1; i++) {
            result += split[i];
        }
        result += new Date().getTime() + "." + split[split.length - 1];
    }
    try {
        fileService.saveFile(result, uploadedInputStream);
        persistenceService.saveDocument(fileName, id, documentTypeId);
    } catch (IOException e) {
        LOGGER.log(Level.SEVERE, "File saving failed", e);
       //TODO Throw exception
    }

    return Response.ok().build();
}
@POST
@路径(“护照”)
@使用(MediaType.MULTIPART\u FORM\u数据)
公共响应saveDocument(@FormDataParam(“文件”)InputStream uploadedInputStream,
@FormDataParam(“文件”)FormDataContentDisposition文件详细信息,
@FormDataParam(“documentTypeId”)int documentTypeId,
@FormDataParam(“id”)int id){
字符串fileName=fileDetail.getFileName();
字符串结果=”;
String[]split=fileName.split(\\);
如果(split.length==1){
//没有分机
结果=拆分[0]+新日期().getTime();
}否则{
对于(int i=0;i

若我以这种方式保存它,那个么我无法确保若在事务期间发生异常,那个么该文件不会被保存。逻辑上的方法是在事务中更新数据库后进行保存,以便在发生异常时回滚事务。但我不确定在事务中执行I/O操作是否是一种好的做法

这并不简单!原因是,很难在“库”级别执行一个通用性足以跨所有文件系统工作的完整回滚系统。您可能认为这很容易,但事实并非如此,并且需要操作系统和文件系统支持

以下面的示例为例,如果要写入新文件,回滚就是删除该文件。如果要删除一个文件,回滚就是取消删除它(需要操作系统支持)。最后,如果要修改文件,则需要返回到事务之前的状态(需要访问某些文件系统上的日志记录)

现在,为了完全原子化,Java库需要直接与新闻系统一起工作,这样即使JVM在事务中崩溃,JFS也会回滚文件更改


考虑使用文件系统层,甚至某种NoSQL数据库,而不是保存到文件中?

这并不简单!原因是,很难在“库”级别执行一个通用性足以跨所有文件系统工作的完整回滚系统。您可能认为这很容易,但事实并非如此,并且需要操作系统和文件系统支持

以下面的示例为例,如果要写入新文件,回滚就是删除该文件。如果要删除一个文件,回滚就是取消删除它(需要操作系统支持)。最后,如果要修改文件,则需要返回到事务之前的状态(需要访问某些文件系统上的日志记录)

现在,为了完全原子化,Java库需要直接与新闻系统一起工作,这样即使JVM在事务中崩溃,JFS也会回滚文件更改


考虑使用文件系统层,甚至某种类型的NoSQL数据库,而不是保存到文件中?

您可以使用文件系统处理事务性操作,也可以使用文件系统处理事务性操作。我假设事务确实是原子的,如果从内部引发任何异常,它会导致回滚。所以我想,我可以先更新数据库,然后保存文件。若保存文件引发异常,我可能会重新引发该异常,事务将失败,导致它回滚。但我不确定I/O操作是否应该在事务中完成。这就是问题所在,目前FileIO在某些文件系统上只是原子的。看看这个:是的,但如果我在事务中使用它,我不关心它的原子性。我只关心事务是原子的,这就是问题所在。如果JVM崩溃会发生什么?或者如果操作系统崩溃或出现电源故障?对于要将事务应用到文件io的标准库,它需要遵循与dB事务相同的规则。好吧,我假设事务确实是原子的,如果从内部抛出任何异常,它会导致回滚。所以我想,我可以先更新数据库,然后保存文件。若保存文件引发异常,我可能会重新引发该异常,事务将失败,导致它回滚。但我不确定I/O操作是否应该在事务中完成。这就是问题所在,目前FileIO在某些文件系统上只是原子的。看看这个:是的,但如果我在事务中使用它,我不关心它的原子性。我只关心事务是原子的,这就是问题所在。如果JVM崩溃会发生什么?或者如果操作系统崩溃或出现电源故障?对于要将事务应用到文件io的标准库,它需要遵循与dB事务相同的规则。