Mã của bạn về cơ bản là chính xác. Ngoại lệ được đưa ra khi xảy ra khóa chết là SQLException
. getSQLState()
của ngoại lệ phương thức cung cấp trả về mã lỗi cung cấp thông tin bổ sung
về lỗi thực tế.
Bạn cũng nên đợi một khoảng thời gian ngắn giữa các lần tham dự để không tải máy chủ của bạn quá nhiều.
Như bạn đã đoán khéo léo, hãy đặt số lần thử tối đa, nếu không bạn có thể kết thúc trong một vòng lặp vô hạn.
Mã cuối cùng có thể trông như thế này:
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);
Rõ ràng đoạn mã trên là tối ưu phụ. Bạn có thể muốn phân biệt lỗi diễn ra tại thời điểm kết nối và lỗi tại thời điểm thực thi. Bạn cũng có thể phát hiện ra rằng sau một số lỗi, có rất ít hy vọng rằng nỗ lực khác sẽ hoạt động (ví dụ:thông tin đăng nhập sai hoặc lỗi cú pháp SQL).
Bạn đã hỏi rất nhiều câu hỏi, nhưng tôi sẽ cố gắng trả lời tất cả:
Có, hãy xem ở trên:SQLException
là những cái đó, với nhiều thông tin hơn được cung cấp bởi getErrorCode()
hoặc getSQLState()
.
Một SQLException
có thể được ném bởi hầu như tất cả các phương thức của tất cả các lớp từ java.sql
gói hàng.
Có, xem ở trên.
Rõ ràng là bạn không được tạo lại PreparedStatement
giữa hai truy vấn. Bạn chỉ cần đặt các giá trị mới cho các tham số của mình trước khi gọi executeQuery()
lần nữa. Tất nhiên, nếu bạn cần thực hiện một truy vấn khác, thì một PreparedStatement
mới là bắt buộc.
A (mới) ResultSet
đối tượng được trả về bởi Statement.executeQuery()
, đại diện cho kết quả của truy vấn. Bạn không bao giờ tự mình tạo ra một đối tượng như vậy. Lý tưởng nhất là bạn sẽ gọi ResultSet.close()
càng sớm càng tốt để giải phóng bộ nhớ.
Tôi thực sự khuyên bạn nên làm theo chương thứ hai của hướng dẫn này ("Xử lý câu lệnh SQL").