【发布时间】:2021-11-10 13:51:14
【问题描述】:
在为我的应用程序编写 JUnit 测试时,我遇到了一个问题,好像当我关闭 EntityManager 和 EntityManagerFactory 时,需要一些时间才能完成,并且我无法复制数据库 (H2) 文件夹马上。
让我更详细地解释一下:
这是我的单个 JUnit 测试中的内容(我只是在 DatabaseManager 上调用此静态方法):
DatabaseManager.createBackupNoAlert(new File(DatabaseManager.getConnectedDatabasePath()), new File(TESTDBBACKUPPATH));
这里两个文件都不为空,并且使用EntityManager和EntityManagerFactory成功创建了数据库连接。
createBackupNoAlert方法:
public static void createBackupNoAlert(final File actualDb, final File destination)
{
try
{
if (!destination.exists())
{
destination.mkdir();
}
DatabaseManager.disconnect();
FileUtils.copyDirectoryToDirectory(actualDb, destination);
String now = LocalDateTime.now().toString();
now = now.substring(0, now.indexOf('.')).replaceAll(":", "_");
File newFile = new File(destination.getAbsolutePath() + "\\" + now);
boolean renamedToCurrentDateTime = new File(destination, actualDb.getName()).renameTo(newFile);
if (!renamedToCurrentDateTime)
{
logger.warn("Could not rename backup directory to current datetime");
}
DatabaseManager.renewConnection();
}
catch (IOException e)
{
logger.error(ExceptionUtils.getStackTrace(e));
}
}
对于复制数据库文件夹,我正在使用 commons-io https://mvnrepository.com/artifact/commons-io/commons-io/2.11.0 中的 FileUtils.copyDirectoryToDirectory() 方法。
disconnect方法:
public static void disconnect()
{
if (entityManager != null && entityManager.isOpen())
{
entityManager.close();
}
if (entityManagerFactory != null && entityManagerFactory.isOpen())
{
entityManagerFactory.close();
}
logger.info("Disconnected from db");
}
.close() 两个方法都被调用。
运行此测试时,FileUtils.copyDirectoryToDirectory(actualDb, destination); 发生异常:
java.nio.file.FileSystemException: testdb\testdb.mv.db -> backuptestdb\testdb\testdb.mv.db:进程无法访问文件 因为另一个进程锁定了文件的一部分
disconnect() 完成后,没有更多与数据库的连接。
上述陈述的证明以及我尝试和发现的内容:
当我在 FileUtils.copyDirectory... 处插入断点并在调试模式下运行该测试 (DatabaseManager.createBackupNoAlert()) 时,稍等片刻,继续,复制目录,一切正常,测试完成。我在想的是 Hibernate 在另一个线程上运行 EntityManager.close() 和 EntityManagerFactory.close(),在我调用该复制操作之前它没有完成,但在我查看实现之后它没有完成。
另外,当我在DatabaseManager.disconnect() 和FileUtils.copyDirectoryToDirectory() 之间插入Thread.sleep(100) 时,测试可以完成!
其他人遇到过这种情况吗?是否有任何修复程序可以让我在关闭与数据库的连接后立即复制数据库文件夹?
我在连接中使用的 Hibernate 属性:
hibernateProps.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
hibernateProps.put("hibernate.connection.pool_size", "1");
hibernateProps.put("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
hibernateProps.put("hibernate.c3p0.min_size", "1");
hibernateProps.put("hibernate.c3p0.max_size", "1");
hibernateProps.put("hibernate.c3p0.acquireRetryAttempts", "3");
hibernateProps.put("hibernate.c3p0.acquireRetryDelay", "400");
hibernateProps.put("hibernate.connection.isolation", String.valueOf(Connection.TRANSACTION_SERIALIZABLE));
hibernateProps.put("javax.persistence.schema-generation.database.action", "create");
【问题讨论】:
-
您使用连接池 (C3P0),它将保持连接打开(我不确定在这种情况下 C3P0 是否也被释放,但这可能会在实际关闭时引入额外的延迟)。如果您将 DB_CLOSE_DELAY 设置为 0 以外的任何值,还要检查您的 JDBC URL 或连接属性。