Mam blok kodu, który aktualizuje rekordy w bazie danych. Zmniejszone przykład:Czy mogę ponownie użyć PreparedStatement, jeśli wystąpi wyjątek przejściowy?
...
statement = connection.prepareStatement(
"INSERT INTO thistable (name) VALUES (?)",
PreparedStatement.RETURN_GENERATED_KEYS
);
statement.setString(1, "Fred");
statement.addBatch();
statement.setString(2, "Joe");
statement.addBatch();
statement.executeBatch();
...
Jest to część jakiegoś kodu, który przetwarza dużo zapisów, a kod działa wiele wątków do prędkości. Wszystko jest w porządku, ale gdy obciążenie wzrasta w środowisku na żywo, zauważyłem, że kilka rzutujących jest SQLTransientException
s. Wygląda na to, że nie mogę nic z tym zrobić, z wyjątkiem ponownej próby transakcji.
Moje pytanie brzmi: czy partia mogła zostać wyczyszczona, nawet jeśli instrukcja nie powiodła się? Czy mogę po prostu powtórzyć linię executeBatch
, czy muszę ponownie utworzyć całą partię? Czy jest to to samo w przypadku oświadczeń innych niż wsadowe?
Krótko mówiąc, czy jest to dobry sposób na obsługę wyjątków przejściowych?
statement.setString(1, "Fred");
statement.addBatch();
statement.setString(2, "Joe");
statement.addBatch();
for(int attempt = 0; ; attempt ++) {
try {
statement.executeBatch();
break;
} catch(SQLTransientException ex) {
if(attempt >= 3) {
throw ex;
}
try {
Thread.sleep(attempt * attempt * 100);
} catch(InterruptedException ex2) {
throw ex;
}
}
}
Oznaczyłem to pytanie MySQL, ponieważ właśnie tego używamy, ale staram się zrozumieć standardowe zachowanie, a nie zachowanie zależne od implementacji, ponieważ wkrótce przeprowadzamy migrację do PostgreSQL. – Dave
Teoretycznie "SQLTransientException" powinno być zgłaszane tylko wtedy, gdy błąd pozwala na operacje, które mogą być ponawiane bez "bez interwencji przez funkcjonalność na poziomie aplikacji". –
Czy masz jakieś państwo SQL dla tego wyjątku (getSQLState())? – Mani