如何从close文件方法抛出IOException时管理事务(包括文件IO)

时间:2011-03-09 12:20:54

标签: java file-io transactions spring-transactions

我最近开始使用Spring的数据源事务管理器。我现在有问题。 我的事务包括对DB表的更新和对文件的写入操作。

它工作正常,但我对文件I / O有些怀疑。如下所示,我已经将bean的openFile和closeFile方法分别配置为init-method和destroy-method,这反过来又提供了这些方法,就像一个constuructor和一个析构函数一样。如果文件没有正确关闭,某些记录可能没有成功写入output.txt文件,这意味着我还无法正确处理事务管理。

但是,我想回滚那些尚未附加到平面文件的数据库更新。使用我的解决方案,看起来无法将fileClose方法添加到事务中。有谁知道如何正确实施这个想要的行动?

任何建议都将不胜感激

<!--XML CONFIGURATION -->
<bean id="myFileWriter" class="com.job.step.ItemFileWriter"  init-method="openFile" destroy-method="closeFile">
    <property name="jdbcTemplate" ref="jdbcTemplateProduct"/>   
</bean> 

public class ItemFileWriter implements ItemWriter<Item> {
private static final Logger log = Logger.getLogger(ItemFileWriter.class);   
private BufferedWriter bw = null;
public void openFile() throws IOException {
    try {
        bw = new BufferedWriter(new FileWriter("C:\\output.txt"));
    } catch (IOException e) {           
        //log.error(e);
        throw e;
    }       
}
public void closeFile() throws IOException {
    if (bw != null) {
        try {
            bw.close();
        } catch (IOException e) {
            log.error(e);
            throw e;
        }
    }
}

@Transactional(rollbackFor = IOException.class)
public void write(List<? extends Item> itemList) throws IOException 
{               
    for (Iterator<? extends Item> iterator = itemList.iterator(); iterator.hasNext();) {
        Item item = (Item) iterator.next();

        String updateRtlnOutbound = "UPDATE SAMPLESCHEMA.SAMPLETABLE SET STATUS='TRANSFERRED' WHERE ID = ?";
        jdbcTemplate.update(updateRtlnOutbound, new Object[]{item.getID()});

        String item = String.format("%09d\n", item.customerNumber);
        bw.write(item);
    }                           
}
}   

2 个答案:

答案 0 :(得分:4)

一般来说,文件IO不是事务性的(某些特定于操作系统的功能除外)。

因此,您可以做的最好的事情是将打开和关闭操作移动到write()方法,以便在事务中执行它们并在关闭失败时回滚事务。

但请注意,在事务回滚的情况下,您无法回滚文件IO,因此在某些情况下您可以使用项目获取正确的文件,而在数据库中这些项目不会标记为{{1 }}

要解决此问题,您可以尝试使用low-level transaction management support并尝试在回滚的情况下删除该文件,但我认为它仍然无法提供强大的一致性保证:

TRANSFERRED

答案 1 :(得分:2)

您正在两个不同的系统上进行操作:文件系统和数据库。通常,XA事务使我们可以轻松地将不同的事务系统组合到单个事务中。

大多数数据库都可以参与XA事务。对于文件系统,您可以使用XADisk启用XA。一旦在两个数据库(通过正确配置数据源)和文件系统(通过xadisk)上启用XA,您就可以确保文件和数据库操作都提交或者两者都回滚。