Java 当close File方法引发IOException时,如何管理事务(包括文件IO)
我最近开始使用Spring的数据源事务管理器。我现在有个问题。 我的事务包括对DB表的更新和对文件的写入操作 它工作得很好,但我对文件I/O有些怀疑。正如您在下面看到的,我已经将bean的openFile和closeFile方法分别配置为init方法和destroy方法,这反过来又提供了这些方法,可以像constructor和destrouctor一样调用它们。如果文件未正确关闭,则某些记录可能未成功写入output.txt文件,这意味着我也无法正确处理事务管理 但是,我想回滚那些尚未附加到平面文件的DB更新。在我的解决方案中,似乎不可能将fileClose方法添加到事务中。有人知道如何正确地实施这个期望的行动吗 如有任何建议,将不胜感激Java 当close File方法引发IOException时,如何管理事务(包括文件IO),java,file-io,transactions,spring-transactions,Java,File Io,Transactions,Spring Transactions,我最近开始使用Spring的数据源事务管理器。我现在有个问题。 我的事务包括对DB表的更新和对文件的写入操作 它工作得很好,但我对文件I/O有些怀疑。正如您在下面看到的,我已经将bean的openFile和closeFile方法分别配置为init方法和destroy方法,这反过来又提供了这些方法,可以像constructor和destrouctor一样调用它们。如果文件未正确关闭,则某些记录可能未成功写入output.txt文件,这意味着我也无法正确处理事务管理 但是,我想回滚那些尚未附加到平面
<!--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);
}
}
}
公共类ItemFileWriter实现ItemWriter{
私有静态最终记录器log=Logger.getLogger(ItemFileWriter.class);
private BufferedWriter bw=null;
public void openFile()引发IOException{
试一试{
bw=新的BufferedWriter(新的文件写入程序(“C:\\output.txt”);
}捕获(IOE){
//日志错误(e);
投掷e;
}
}
public void closeFile()引发IOException{
如果(bw!=null){
试一试{
bw.close();
}捕获(IOE异常){
日志错误(e);
投掷e;
}
}
}
@事务性(rollboor=IOException.class)
public void write(List一般来说,文件IO不是事务性的(除了某些特定于操作系统的功能)
因此,最好将打开和关闭操作移动到write()
方法,以便在事务中执行它们,并在关闭失败时回滚事务
但是,请注意,在事务回滚的情况下,您无法回滚文件IO,因此在某些情况下,您可以获得包含项的正确文件,而在数据库中,这些项没有标记为已传输的
要解决此问题,您可以尝试在回滚的情况下使用并删除该文件,但我认为它仍然无法提供一致性的有力保证:
@Transactional(rollbackFor = IOException.class)
public void write(List<? extends Item> itemList) throws IOException
{
openFile();
TransactionSynchronizationManager().registerSynchronization(new TransactionSynchronizationAdapter() {
public void afterCompletion(int status) {
if (status = STATUS_ROLLED_BACK) {
// try to delete the file
}
}
});
try {
...
} finally {
closeFile();
}
}
@Transactional(rollboor=IOException.class)
public void write(List您在两个不同的系统上执行操作:文件系统和数据库。通常,XA事务使我们能够轻松地将不同的事务系统组合到单个事务中
大多数数据库都可以参与XA事务。对于文件系统,可以使用来启用XA。在数据库(通过正确配置数据源)和文件系统(通过xadisk)上启用XA后,可以确保文件和数据库操作都提交或都回滚