我正在尝试创建一个多线程应用程序(Java),其中一些线程将更多行插入数据库。我使用JDK的Embedded Derby。
这是与建立数据库连接和插入有关的代码。
public class DatabaseConnection
{
private static String dbURL = "jdbc:derby:./Database/DB;create=true;user=fafejs;password=fafejs";
private Connection conn;
private DatabaseUpdateContent duc;
private DatabaseUpdateView duv;
public synchronized void createConnection()
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); // load the driver
conn = DriverManager.getConnection(dbURL); // make Derby JDBC connection
duc = new DatabaseUpdateContent(conn);
duv = new DatabaseUpdateView(conn);
System.out.println(conn);
}
catch (Exception except) // TODO - obsluga
{
except.printStackTrace();
}
}
public synchronized void recreateConnection()
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
conn = DriverManager.getConnection(dbURL);
duc = new DatabaseUpdateContent(conn);
duv = new DatabaseUpdateView(conn);
System.out.println("Reconnect:" + conn);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public boolean updatePlayer(PlayerService player)
{
try
{
int ID = player.getID();
String firstName = player.getFirstName();
String lastName = player.getLastName();
Date birthdate;
if(!(player.getDate() == null))
birthdate = new java.sql.Date(player.getDate().getTime());
else
birthdate = null;
String league = newLeagueName(player.getLeagueName()).toUpperCase();
String team = player.getTeamName();
int apps = player.getApps();
int firstSquad = player.getFirstSquad();
int minutes = player.getMinutes();
int goals = player.getGoals();
int yellowCards = player.getYellowCards();
int redCards = player.getRedCards();
duc.updatePlayersTable(ID, firstName, lastName, birthdate);
duc.updateLeagueTable(league, ID, team, apps, firstSquad, minutes, goals, yellowCards, redCards);
return true;
}
catch (SQLException sqlExcept)
{
//shutdown();
sqlExcept.printStackTrace();
return false;
}
}
public synchronized void shutdown()
{
try
{
DriverManager.getConnection(dbURL + ";shutdown=true");
conn.close();
//System.gc();
}
catch (SQLException sqlExcept)
{
//sqlExcept.printStackTrace();
}
}
}
public void updatePlayersTable(int ID, String firstName, String lastName, Date birthdate) throws SQLException // z klasy DatabaseUpdateContent
{
PreparedStatement pstmt = conn.prepareStatement("UPDATE APP.PLAYERS SET FIRST_NAME = ?, LAST_NAME = ?, BIRTHDATE = ? WHERE ID = ?");
pstmt.setString(1,firstName);
pstmt.setString(2,lastName);
pstmt.setDate(3,birthdate);
pstmt.setInt(4,ID);
if(pstmt.executeUpdate() == 0)
{
pstmt = conn.prepareStatement("INSERT INTO APP.PLAYERS VALUES (?,?,?,?)");
pstmt.setInt(1, ID);
pstmt.setString(2, firstName);
pstmt.setString(3, lastName);
pstmt.setDate(4, birthdate);
pstmt.execute();
}
pstmt.close();
}
public void updateDB() // procedura, która zajmuje się aktualizacją zawartości bazy danych
{
DatabaseConnection database = new DatabaseConnection();
database.createConnection();
for(PlayerService player: players)
{
while(!database.updatePlayer(player))
{
database.recreateConnection();
}
}
database.shutdown();
}
总的来说,大多数行都被正确地插入到适当的表中,但有时我会得到SQLNonTransientConnectionException:
java.sql.SQLNonTransientConnectionException: No current connection.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.noCurrentConnection(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.checkIfClosed(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.setupContextStack(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
at DatabaseService.DatabaseUpdateContent.updateLeagueTable(DatabaseUpdateContent.java:39)
at DatabaseService.DatabaseConnection.updatePlayer(DatabaseConnection.java:68)
at DataService.TeamService.updateDB(TeamService.java:66)
at DataService.TeamService.getPlayers(TeamService.java:56)
at DataService.TeamService.getPlayersUrls(TeamService.java:44)
at DataService.LeagueService.getTeams(LeagueService.java:52)
at DataService.LeagueService.run(LeagueService.java:35)
at java.lang.Thread.run(Thread.java:745)
Caused by: ERROR 08003: No current connection.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 17 more
java.sql.SQLException: Database './Database/DB' not found.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.handleDBNotFound(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.<init>(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.getNewEmbedConnection(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
at org.apache.derby.jdbc.AutoloadedDriver.connect(Unknown Source)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at DatabaseService.DatabaseConnection.recreateConnection(DatabaseConnection.java:35)
at DataService.TeamService.updateDB(TeamService.java:69)
at DataService.TeamService.getPlayers(TeamService.java:56)
at DataService.TeamService.getPlayersUrls(TeamService.java:44)
at DataService.LeagueService.getTeams(LeagueService.java:52)
at DataService.LeagueService.run(LeagueService.java:35)
at java.lang.Thread.run(Thread.java:745)
Caused by: ERROR XJ004: Database './Database/DB' not found.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 20 more
此异常连续多次发生,因为如果更新播放器失败,函数updatePlayer将返回false,我们在函数updateDB中重复循环。但过了一会儿(大约50次插入行的尝试),就可以建立连接并插入一行。
当然我已经找到了解决这个问题的方法。我尝试过与System.gc()相关的方法,在某些文档中提出了什么建议,但在我的情况下没有用。
我还在考虑我的问题可能与我的应用程序的多线程有关,但在Embedded Derby的文档中他们简单地说嵌入式Derby应该处理它。
感谢你的支持。
修改
这是我从http://wiki.apache.org/db-derby/UnwindExceptionChain添加代码后收到的错误信息:
----- SQLException -----
SQLState: 08003
Error Code: 40000
Message: No current connection.
java.sql.SQLNonTransientConnectionException: No current connection.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.noCurrentConnection(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.checkIfClosed(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.setupContextStack(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
at DatabaseService.DatabaseUpdateContent.updatePlayersTable(DatabaseUpdateContent.java:17)
at DatabaseService.DatabaseConnection.updatePlayer(DatabaseConnection.java:73)
at DataService.TeamService.updateDB(TeamService.java:64)
at DataService.TeamService.getPlayers(TeamService.java:53)
at DataService.TeamService.getPlayersUrls(TeamService.java:39)
at DataService.LeagueService.getTeams(LeagueService.java:50)
at DataService.LeagueService.run(LeagueService.java:36)
at java.lang.Thread.run(Thread.java:745)
Caused by: ERROR 08003: No current connection.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 17 more
java.sql.SQLException: Database './Database/DB' not found.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.handleDBNotFound(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.<init>(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.getNewEmbedConnection(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
at org.apache.derby.jdbc.AutoloadedDriver.connect(Unknown Source)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at DatabaseService.DatabaseConnection.recreateConnection(DatabaseConnection.java:39)
at DataService.TeamService.updateDB(TeamService.java:67)
at DataService.TeamService.getPlayers(TeamService.java:53)
at DataService.TeamService.getPlayersUrls(TeamService.java:39)
at DataService.LeagueService.getTeams(LeagueService.java:50)
at DataService.LeagueService.run(LeagueService.java:36)
at java.lang.Thread.run(Thread.java:745)
Caused by: ERROR XJ004: Database './Database/DB' not found.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 20 more
在我看来,与未找到数据库相关的错误(更确切地说,我的意思是与加载嵌入式Derby的驱动程序有关的问题)是由SQLNonTransientConnectionException引起的,并且存在问题。