Din kod är i princip korrekt. Undantaget som uppstår när ett dödlås inträffar är en SQLException
. Undantagets getSQLState()
metod tillhandahåller returnerar en felkod som ger ytterligare information
om det faktiska felet.
Du bör också vänta en kort tid mellan försöken för att inte ladda din server för mycket.
Som du skickligt gissade, ställ in ett maximalt antal försök, annars kan du hamna i en oändlig loop.
Den slutliga koden kan se ut så här:
boolean oops;
int retries = 5;
Connection c = null;
Statement s = null;
ResultSet rs = null;
do
{
oops = false;
c = null;
s = null;
rs = null;
try
{
c = openConnection();
s = c.createStatement();
rs = s.executeQuery("SELECT stuff FROM mytable");
fiddleWith(rs);
}
catch (SQLException sqlex)
{
oops = true;
switch(sqlex.getErrorCode()())
{
case MysqlErrorNumbers.ER_LOCK_DEADLOCK:
// deadlock or lock-wait time-out occured
break;
...
}
Thread.sleep(1000); // short delay before retry
}
finally
{
if (rs != null) try {
rs.close();
} catch (SQLException e) {
// some error handler here
}
if (s != null) try {
s.close();
} catch (SQLException e) {
// some error handler here
}
if (c != null) try {
c.close();
} catch (SQLException e) {
// some error handler here
}
}
}
while (oops == true && retries-- > 0);
Uppenbarligen är ovanstående kod suboptimal. Du kanske vill skilja på fel som uppstår vid anslutningstidpunkten och fel vid körningstidpunkten. Du kan också upptäcka att efter vissa fel finns det lite hopp om att ett nytt försök kommer att fungera (t.ex. felaktiga referenser eller SQL-syntaxfel).
Du ställde många frågor, men jag ska försöka besvara dem alla:
Ja, se ovan:SQLException
s är de, med mer information tillhandahållen av getErrorCode()
eller getSQLState()
.
En SQLException
kan kastas av praktiskt taget alla metoder av alla klasser från java.sql
paket.
Ja, se ovan.
Självklart får du inte återskapa en PreparedStatement
mellan två frågor. Du behöver bara ställa in nya värden för dina parametrar innan du anropar executeQuery()
på nytt. Naturligtvis om du behöver köra en annan fråga, sedan en ny PreparedStatement
krävs.
En (ny) ResultSet
objektet returneras av Statement.executeQuery()
, som representerar resultatet av frågan. Du skapar aldrig ett sådant objekt själv. Helst anropar du ResultSet.close()
så snart som möjligt för att frigöra minnet.
Jag rekommenderar starkt att du följer det andra kapitlet i denna handledning ("Bearbetar SQL-satser").