我有一个Spring Batch作业正在读取指定的Access数据库文件。我使用uncanaccess
JDBC库来执行此操作。一旦作业退出,无论作业是否成功完成,我都需要让我的应用程序将访问文件移动到另一个文件夹。目前我收到java.nio.file.FileSystemException
表示无法移动,因为它已被其他进程使用。我假设其他进程是由于JDBC连接已打开这一事实。
Exception in thread "main" com.mycompany.weeklyimport.FileException: Failed to move file [C:\temp\hold\temp.mdb] to [C:\temp\error\temp.mdb]
at com.mycompany.weeklyimport.WeeklyImportApplication.moveFile(WeeklyImportApplication.java:365)
at com.mycompany.weeklyimport.WeeklyImportApplication.main(WeeklyImportApplication.java:91)
Caused by: java.nio.file.FileSystemException: C:\temp\hold\temp.mdb -> C:\temp\error\temp.mdb: The process cannot access the file because it is being used by another process.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:387)
at sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:287)
at java.nio.file.Files.move(Files.java:1395)
at com.mycompany.weeklyimport.WeeklyImportApplication.moveFile(WeeklyImportApplication.java:363)
... 1 more
这是我的主程序(通过Spring Boot运行Spring作业):
@SpringBootApplication
@EnableBatchProcessing
@Slf4j
public class WeeklyImportApplication extends DefaultBatchConfigurer {
...
private static String inputFile;
private static boolean exceptionEncountered = false;
public static void main(String[] args) throws Throwable {
handleArguments(args);
ConfigurableApplicationContext context = new SpringApplicationBuilder(WeeklyImportApplication.class).listeners(new CustomLoggingConfigurationApplicationListener(logConfigurer)).run(args);
if (exceptionEncountered) {
moveFile("error");
} else {
moveFile("complete");
}
finished();
}
private static void moveFile(String folderName) {
File file = new File(inputFile);
File newPath = new File(file.getParentFile().getParentFile().getPath() + File.separator + folderName);
if (!newPath.exists()) {
if (!newPath.mkdirs()) {
throw new FileException("Failed to create folder [" + newPath.getPath() + "]");
}
}
File newFile = new File(newPath.getPath() + File.separator + file.getName());
try {
Files.move(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
throw new FileException("Failed to move file [" + file.getPath() + "] to [" + newFile.getPath() + "]", ex);
}
}
...
我的数据源配置。我也指定一个静态变量,以便在Spring退出后尝试关闭连接。
@Configuration
public class DataSourceConfiguration {
public static SingleConnectionDataSource legacyDataSource;
@Bean(name = "importDataSource")
public DataSource importDataSource() {
SingleConnectionDataSource dataSource = new SingleConnectionDataSource();
dataSource.setDriverClassName(this.importDriver.trim());
dataSource.setSuppressClose(true);
dataSource.setUrl("jdbc:ucanaccess://" + WeeklyImportApplication.getInputFile());
return dataSource;
}
...
我尝试过以下方法:
DataSourceConfiguration.legacyDataSource.getConnection().close();
DataSourceConfiguration.legacyDataSource.destroy();
DataSourceConfiguration.legacyDataSource = null;
不知何故,某些内容仍然锁定该文件。有没有人遇到过这样的事情,或者对如何强制读取文件的真正结束有任何想法?
解决
jamadei在下面的回答帮助我找到了这个解决方案。相关解决方案代码:@Bean(name = "importDataSource")
public DataSource importDataSource() {
SingleConnectionDataSource dataSource = new SingleConnectionDataSource();
dataSource.setDriverClassName(this.importDriver.trim());
dataSource.setSuppressClose(true);
dataSource.setUrl("jdbc:ucanaccess://" + WeeklyImportApplication.getInputFile() + ";SingleConnection=true");
importDataSource = dataSource;
return dataSource;
}
public static void main(String[] args) throws Throwable {
handleArguments(args);
new SpringApplicationBuilder(WeeklyImportApplication.class).listeners(new CustomLoggingConfigurationApplicationListener(logConfigurer)).run(args);
DataSourceConfiguration.importDataSource.setSuppressClose(false);
DataSourceConfiguration.importDataSource.destroy();
if (exceptionEncountered) {
moveFile("error");
System.exit(1);
} else {
moveFile("complete");
}
finished();
}
答案 0 :(得分:2)
它不仅仅是一个Spring问题,而是一个UCanAccess优化/缓存副作用。 你所做的似乎很好,但还不够。 在jdbc url中使用SingleConnection = true参数可以解决问题。