英文:
java.sql.SQLException: The database has been closed at DriverManager.getConnection(url) on Bamboo only
问题
我现在是你的中文翻译,以下是翻译好的部分:
我处于一个尴尬的境地,一些测试在本地运行正常,但一旦推送到仓库并由 Bamboo 构建时就会引发异常。
在 Bamboo 上出现的错误如下:
java.sql.SQLException: 数据库已关闭
它发生在这里,就在 conn = DriverManager.getConnection(url)
这一行:
public RequirementRepository(String folder) throws SQLException, DatabaseNotConnectedException {
new File(folder).mkdirs();
String url = "jdbc:sqlite:" + folder + "/requirement.db";
// create a connection to the database
conn = DriverManager.getConnection(url);
try (Statement statement = conn.createStatement()) {
[非常长的 SQL 语句]
}
}
有趣的是,这并不总是失败,而仅仅是有时候会失败。
我已经在成功和失败的情况下都检查了 URL,两种情况下的 URL 都是相同的:
jdbc:sqlite:Test_Database/requirement.db
有什么想法可以导致或影响这个问题,为什么它只发生在 Bamboo 上而不发生在我的本地机器上?即使我从我的本地机器中删除数据库,以便需要重新创建,我也无法在本地复制这个错误。
编辑:
以下是到达本地代码之前的堆栈跟踪:
java.sql.SQLException: java.sql.SQLException: 数据库已关闭
java.sql.SQLException: 数据库已关闭
at org.sqlite.core.NativeDB.throwex(NativeDB.java:478)
at org.sqlite.core.NativeDB.errmsg_utf8(Native Method)
at org.sqlite.core.NativeDB.errmsg(NativeDB.java:144)
at org.sqlite.core.DB.newSQLException(DB.java:953)
at org.sqlite.core.DB.throwex(DB.java:918)
at org.sqlite.core.NativeDB._open_utf8(Native Method)
at org.sqlite.core.NativeDB._open(NativeDB.java:78)
at org.sqlite.core.DB.open(DB.java:195)
at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:243)
at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:61)
at org.sqlite.jdbc3.JDBC3Connection.<init>(JDBC3Connection.java:28)
at org.sqlite.jdbc4.JDBC4Connection.<init>(JDBC4Connection.java:21)
at org.sqlite.JDBC.createConnection(JDBC.java:116)
at org.sqlite.JDBC.connect(JDBC.java:90)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at dom_requirement.model.RequirementRepository.<init>(RequirementRepository.java:225)
225 行是:
conn = DriverManager.getConnection(url);
编辑 2:
这也在连接被设置为以下内容时出现:
public WorkspaceManager(String folder) throws SQLException {
new File(folder).mkdirs();
databaseConnectionUrl = "jdbc:sqlite:" + folder + "/workspace.db";
// create a connection to the database
try(Connection conn = DriverManager.getConnection(databaseConnectionUrl)){
try (Statement statement = conn.createStatement()) {
[非常长的 SQL 语句]
}
}
}
在这种情况下,导致错误的行是:
try(Connection conn = DriverManager.getConnection(databaseConnectionUrl)){
堆栈跟踪本身保持不变。
编辑 3:
我现在找到了一种方法使它工作,尽管那种特定的解决方法似乎更像是解决了一个故障而不是一个正确的解决方法,所以我仍然对听到可能导致这个问题的想法以及如何解决它感兴趣。
如上所述,错误只出现在 Bamboo 上的测试中。总共有 134 个测试分布在 14 个类中,所有这些类都继承自 RequirementControllerTest 抽象类。
在在 Bamboo 上失败的版本中,SQL 连接是在 RequirementControllerTest 中的 @BeforeEach 方法中创建的,因此为这 134 个测试中的每一个都创建了一个新的连接。
我们通过将这个 @BeforeEach 方法切换为 @BeforeAll 方法来使其通过,所以现在 SQL 连接只会被创建 14 次,而不是 134 次,有趣的是这在 Bamboo 上可以工作。
所以我现在想知道的是,如果只做 14 次就可以工作,那么做 134 次为什么不行呢?为什么这只会发生在 Bamboo 上呢?
英文:
I am in the uncomfortable situation where some tests work locally, but cause an exception once pushed to the repository and the build by Bamboo.
The error that occurs on Bamboo is as follows:
java.sql.SQLException: The database has been closed
It occurs here, in the line conn = DriverManager.getConnection(url)
:
public RequirementRepository(String folder) throws SQLException, DatabaseNotConnectedException {
new File(folder).mkdirs();
String url = "jdbc:sqlite:" + folder + "/requirement.db";
// create a connection to the database
conn = DriverManager.getConnection(url);
try (Statement statement = conn.createStatement()) {
[Very long SQL statement]
}
}
Interestingly, this does not fail always, but only sometimes.
I've already checked the URL in both succeeding and failing cases, and it is the same in both cases:
jdbc:sqlite:Test_Database/requirement.db
Any ideas what could cause or affect this, and why it only happens on Bamboo and not on my local machine? Even if I delete the database from my local machine so it has to be newly created, I can't replicate the error locally.
EDIT:
Here's the stack trace up to the point where it enters local code:
java.sql.SQLException: java.sql.SQLException: The database has been closed
java.sql.SQLException: The database has been closed
at org.sqlite.core.NativeDB.throwex(NativeDB.java:478)
at org.sqlite.core.NativeDB.errmsg_utf8(Native Method)
at org.sqlite.core.NativeDB.errmsg(NativeDB.java:144)
at org.sqlite.core.DB.newSQLException(DB.java:953)
at org.sqlite.core.DB.throwex(DB.java:918)
at org.sqlite.core.NativeDB._open_utf8(Native Method)
at org.sqlite.core.NativeDB._open(NativeDB.java:78)
at org.sqlite.core.DB.open(DB.java:195)
at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:243)
at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:61)
at org.sqlite.jdbc3.JDBC3Connection.<init>(JDBC3Connection.java:28)
at org.sqlite.jdbc4.JDBC4Connection.<init>(JDBC4Connection.java:21)
at org.sqlite.JDBC.createConnection(JDBC.java:116)
at org.sqlite.JDBC.connect(JDBC.java:90)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at dom_requirement.model.RequirementRepository.<init>(RequirementRepository.java:225)
Line 225 is:
conn = DriverManager.getConnection(url);
EDIT 2:
This notably also appears when the connection is being set like this:
public WorkspaceManager(String folder) throws SQLException {
new File(folder).mkdirs();
databaseConnectionUrl = "jdbc:sqlite:" + folder + "/workspace.db";
// create a connection to the database
try(Connection conn = DriverManager.getConnection(databaseConnectionUrl)){
try (Statement statement = conn.createStatement()) {
[Very long SQL statement]
}
}
}
In that case, the line causing the error is:
try(Connection conn = DriverManager.getConnection(databaseConnectionUrl)){
The stacktrace itself remains unchanged.
EDIT 3:
I now found a way to make it work, although that particular solution seems more like a workaround around a glitch than a proper solution, so I am still interested in hearing about ideas what might be the actual cause and how to fix it.
As mentioned above, the error appears only on tests on Bamboo. It's a total of 134 tests spread across 14 classes, all of which inherit from a RequirementControllerTest abstract class.
In the version where it fails on Bamboo, the SQL Connection is created in a @BeforeEach method in the RequirementControllerTest, so a fresh connection is created for each of the 134 tests.
We managed to get it to pass by switching this @BeforeEach method to a @BeforeAll method, so now the SQL Connection is only created 14 times instead of 134, and interestingly this works on Bamboo.
So the thing I wonder now is, how can this work if it's only done 14 times, but not if it's done 134 times? And why does it only happen on Bamboo?
答案1
得分: 1
I think the path is wrongly formed in the url
is invalid.
That is, this jdbc:sqlite:Test_Database/requirement.db
is an invalid path formation.
Update the code to this:
public RequirementRepository(String folder) throws SQLException, DatabaseNotConnectedException {
File file = new File(folder);
file.mkdirs();
String url = "jdbc:sqlite:" + file.getAbsolutePath() + "/requirement.db";
try (Connection conn = DriverManager.getConnection(url);
Statement statement = conn.createStatement();) {
[Very long SQL statement]
} catch(SQLException e) {
// TODO: throw exception.
}
}
Note: The folder
field should contain the full path where the directory should be created.
For example:
String folder = "D:/Test_Database";
Follow this syntax:
jdbc:sqlite:db_file_path
- here db_file_path
should be an absolute or relative path.
For example:
jdbc:sqlite:D:/Test_Database/requirement.db or jdbc:sqlite:requirement.db
Follow this blog.
Read this Bamboo's working directory Atlassian Support.
英文:
I think the path is wrongly formed in the url
is invalid.
That is, this jdbc:sqlite:Test_Database/requirement.db
is invalid path formed.
Update the code to this :
public RequirementRepository(String folder) throws SQLException, DatabaseNotConnectedException {
File file = new File(folder);
file.mkdirs();
String url = "jdbc:sqlite:" + file.getAbsolutePath() + "/requirement.db";
try (Connection conn = DriverManager.getConnection(url);
Statement statement = conn.createStatement();) {
[Very long SQL statement]
} catch(SQLException e) {
// TODO: throw exception.
}
}
Note : folder
field should contain the full path where the directory should be created.
For example :
String folder = "D:/Test_Database";
Follow this syntax :
jdbc:sqlite:db_file_path
- here db_file_path
should be an absolute or relative path.
For example :
jdbc:sqlite:D:/Test_Database/requirement.db or jdbc:sqlite:requirement.db
Follow this blog
Read this Bamboo's working directory Atlassian Support.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论