2013-05-14 42 views
12

Bất kỳ ai có thể nghĩ ra lý do hợp lý tại sao SQLException là một ngoại lệ được kiểm tra?Tại sao SQLException là ngoại lệ được kiểm tra

Vâng, có thể là một lỗi cú pháp trong truy vấn
Vâng, kết nối có thể đã chết
Vâng, có thể là một vấn đề cho phép
Etc, vv blah blah blah

Nhưng thực tế 100% của thời gian (một khi bạn đang chạy trong sản xuất), không có bất kỳ vấn đề.

Nếu có sự cố, mã gọi điện thoại không thể thực hiện bất cứ điều gì để khôi phục, vì vậy lý do đó phải là không được chọn.

Được kiểm tra tạo khối lượng của các dấu hoa hồng try catch trong suốt mã, vì bất kỳ ai đã tham gia vào dự án sử dụng JDBC sẽ chứng thực. Sự lộn xộn mã là đáng kể.

Vì tính chất bí truyền của SQL, vô số lý do bạn có thể nhận được SQLException và độ phức tạp của chúng có nghĩa là bạn không thể phục hồi, trừ khi ngoại lệ là do sự cố mạng tạm thời, nhưng ngay cả khi có cuộc gọi đồng bộ, bạn đang bị chìm bởi vì bạn không thể chờ đợi vô thời hạn cho vấn đề mạng được giải quyết, vì vậy bạn sẽ phải thất bại trong giao dịch.

Thông thường, gọi SQL trông như thế này:

try { 
    // make some SQL call(s) 
} catch {SQLException e) { 
    // log the exception 
    return; // and give up 
} 

đang như vậy thêm không có giá trị. Không có gì hợp lý bạn có thể làm để phục hồi. Bạn cũng có thể để bong bóng ngoại lệ thời gian chạy lên - tức là SQLException phải là một ngoại lệ thời gian chạy (không được chọn).

+3

A) Mạng, máy chủ cơ sở dữ liệu, cân bằng tải, v.v. không có thời gian tăng 100% B) Bạn chắc chắn nhất có thể làm điều gì đó khi xảy ra lỗi. –

+0

Máy chủ không xảy ra thường xuyên hơn bạn mong đợi và là thứ mà khách hàng sẽ xử lý. (Rất có thể, bằng cách hiển thị thông báo lỗi và thử lại sau). Chủ yếu là với các vấn đề bế tắc. – MTilsted

+1

@BrianRoach OK - nói rằng mạng sẽ biến mất. Mã gọi điện thoại có thể làm gì để đưa mạng trở lại? Không có gì! Vì vậy, một lần nữa, tại sao nó được kiểm tra? Kiểm tra ngụ ý rằng người gọi có thể phục hồi. – Bohemian

Trả lời

0

Có một vài cách tiếp cận với tình trạng khó xử được kiểm tra và không được kiểm tra. Kiểm tra xem mã gọi có thể khôi phục từ ngoại lệ hay không là một cách tiếp cận, tuy nhiên, điều này, tôi đồng ý, không giải thích tại sao SQLExcption là một ngoại lệ được kiểm tra.

Một số khác, được cung cấp bởi Martin Fowler trong cuốn sách "Refactoring" tuyệt vời của mình gợi ý để xác minh thời tiết đó là gọi hoặc gọi phương pháp trách nhiệm để thực hiện một kiểm tra mà có thể gây ra một ngoại lệ.

Nếu phương pháp gọi nên thực hiện kiểm tra trước khi gọi gọi phương pháp (ví dụ như đảm bảo các đối số không phải là không null) sau đó nếu việc kiểm tra này chưa được thực hiện nó rõ ràng là một lỗi lập trình và sau đó là được gọi là phương pháp sẽ bị bỏ một ngoại lệ không được kiểm tra.

Bây giờ nếu nó là gọi phương pháp trách nhiệm để thực hiện việc kiểm tra, bởi vì chỉ có phương pháp này có thể biết làm thế nào để thực hiện kiểm tra như vậy thì ngoại lệ ném từ gọi phương pháp nên kiểm tra.

Trong trường hợp SQLException Tôi nghĩ rằng chỉ lớp này có thể biết:

  • có một lỗi cú pháp trong truy vấn như thế này phụ thuộc vào cơ sở dữ liệu
  • kết nối đã chết
  • có một phép vấn đề
+0

OK. Hãy giả sử để kiểm tra xem cú pháp SQL có chính xác không (bằng cách viết lại trình phân tích cú pháp SQL trong java!), Và nói có một lỗi - bạn sẽ làm gì với nó? Không có gì! Bạn không thể sửa chữa nó, vậy tại sao bạn lại bắt một ngoại lệ? Hành động duy nhất bạn sẽ làm là ghi lại ngoại lệ và ném một ngoại lệ khác - tại sao không chỉ để cho một ngoại lệ không được kiểm tra thấm qua? – Bohemian

+2

Ok, tôi đồng ý, trong hầu hết các trường hợp, đơn đăng ký của bạn sẽ không thể khôi phục trong trường hợp này. Nhưng trong trường hợp "kết nối đã chết", nó có thể dễ dàng phục hồi từ nó bằng cách thiết lập lại kết nối tới cơ sở dữ liệu. Tôi đoán, cách bạn cảm nhận nếu một ngoại lệ có thể phục hồi hoặc không phụ thuộc hoàn toàn vào tác giả của phương thức gọi, có nghĩa là nó không thể được sử dụng làm tiêu chí để quyết định giữa ngoại lệ được kiểm tra và không được kiểm soát. –

1

Một lý do là phương pháp nên loại trừ ngoại lệ phù hợp với mức trừu tượng của phương pháp.

Vì vậy, phương thức tải thông tin từ cơ sở dữ liệu không được tăng SQLException, mà là ResourceNotFoundException hoặc ResourceUnavailableException.

Làm cho kiểm tra SQLException là một cách để buộc người phát triển nắm bắt Ngoại lệ và bọc nó ở cấp độ trừu tượng mới này.

Đối số này được lấy từ Hiệu lực Java Second Edition bởi Joshua Bloch (Mục 61: Ném ngoại lệ phù hợp với trừu tượng).

+0

Nhưng tại sao "tải dữ liệu từ cơ sở dữ liệu" không thành công? Thực tế là, nó không thất bại! Nó có thể "thất bại" trong sence rằng một hàng không được tìm thấy, nhưng điều đó sẽ không ném một SQLException. Và nếu nó thất bại, nó "bùng nổ" và người gọi không thể làm bất cứ điều gì để phục hồi - đó là bản chất của lý do tại sao sử dụng một ngoại lệ không được kiểm soát. – Bohemian

+0

Tôi đồng ý trong hầu hết các trường hợp không có gì để làm ngoại trừ "phát nổ" ứng dụng. Nhưng tôi có thể tưởng tượng một số trường hợp mà bạn không nên. Ví dụ: nếu tồn tại cơ sở dữ liệu sao lưu hoặc thông tin bạn không thể tìm nạp không có trong cơ sở dữ liệu chính (ví dụ: lỗi khi tìm nạp danh sách yêu thích của bạn trên trang web thương mại điện tử). – obourgain

+0

Lưu ý rằng "thông tin không phải là cơ sở dữ liệu chính" sẽ không ném ngoại lệ - bạn sẽ chỉ nhận được một hàng trống. Bạn đang nói về cơ sở dữ liệu chính đã đi xuống - khá thảm khốc. Tôi đã có mã để đối phó với điều đó, không có gì ngăn cản bạn bắt được một SQLException không được kiểm soát và làm điều gì đó. Điều gì sẽ xảy ra nếu những người không có khả năng đó - họ muốn SQLException là một thời gian chạy. – Bohemian

2

thực tế 100% thời gian không có bất kỳ vấn đề nào - Điều này được giới hạn trong quan sát của riêng bạn mà không nói gì về số về các hệ thống khác. Có nhiều hệ thống máy tính khác nhau trên toàn thế giới với nhiều tắc nghẽn khác nhau. Tỷ lệ thành công của bạn gần như là 100%. Những người khác phải đối phó với tỷ lệ phần trăm thấp hơn nhiều.

Quan niệm sai lầm phổ biến là xem xét giới thiệu/xóa ngoại lệ đã kiểm tra theo tần suất của sự xuất hiện của nó. Các ngoại lệ được kiểm tra đóng vai trò là các kênh truyền thông. Như bạn đã biết, mọi phương thức đều có giao diện công khai của nó. Bằng cách này, phương thức cho chúng ta biết các đối số mà nó chấp nhận và kết quả của mã trong phần thân của nó là gì.

Khi nó trở thành không thể cho một phương pháp đang được tiến hành để giữ lời hứa của nó (ví dụ như giá trị trả về) nó cần một cách để nói cho các phương pháp khác rằng một cái gì đó đã đi sai và nó không thể làm những gì được mong đợi. Nhưng làm thế nào để làm điều đó ? Gửi tin nhắn khi giá trị trả lại không hoạt động, hầu như không có cơ hội cho phương thức gọi để phân biệt giữa giá trị thích hợp và thông báo lỗi. Không phải để nói rằng một số phương thức không có giá trị trả về. Vì vậy, bạn làm gì khi bạn không thể giữ lời hứa của bạn được xác định bởi giao diện của phương pháp của bạn? Vâng, bạn ném một ngoại lệ (gửi một tin nhắn).

Nếu bạn mong đợi ResultSet và không có kết nối với cơ sở dữ liệu của bạn thành lập, bạn nên làm gì? Trả về kết quả rỗng? Địa ngục không, điều này cho chúng ta biết rằng cơ sở dữ liệu trống. Trả về null? Vâng, điều này chỉ đại biểu cho vấn đề và làm cho việc tìm kiếm nguyên nhân không rõ ràng.

Bạn có thể sử dụng kết quả trống rỗng đó và biến nó thành một phần của truy vấn khác sang cơ sở dữ liệu khác, làm cho nó không phù hợp.

Không có SQLException, ngay cả một lỗi cũng có thể dẫn đến sự không nhất quán về dữ liệu.

+2

Nếu hệ thống không đạt được phần trăm thời gian đáng kể, mọi người sẽ không sử dụng chúng. Thành công gần 100%, bạn cũng có thể gọi nó là 100%. Tôi không nói với * không * ném một ngoại lệ, chỉ là nó nên được bỏ chọn. Hãy để nó bong bóng lên. Như tôi đã nói, một excpetion kiểm tra ngụ ý người gọi có thể làm một cái gì đó để phục hồi, nhưng với SQL bạn không thể phục hồi. Chính xác thì bạn sẽ làm gì trong mã của mình nếu bạn nhận được một ngoại lệ lỗi cú pháp? Không có gì, đó là những gì! Bạn có thể đăng nhập lỗi và thoát khỏi phương thức - bạn đã thêm không có giá trị. Nó cũng có thể đã không bắt được nó. – Bohemian

1

Ghi ngoại lệ cho phép chúng tôi có khả năng phục hồi từ các điều kiện đặc biệt, đúng, nhưng chúng cũng cho phép chúng tôi làm những việc khác.

Bạn không thể phục hồi từ một SQLException ở chỗ không có nhiều bạn có thể làm gì để giải quyết vấn đề tại thời gian chạy, nhưng có một số điều hữu ích mà bạn có thể làm:

  • Log ngoại trừ để gỡ lỗi thông tin
  • Rollback giao dịch

bạn luôn có thể đăng nhập ngoại trừ ở một mức độ cao hơn (hoặc thấp hơn, tùy thuộc vào quan điểm), nhưng bạn mất một số giá trị ngữ nghĩa, cả ở gỡ lỗi thời gian và khi xem xét các mã.

Nếu bạn làm điều gì đó như:

try { ... } 
catch(SQLException e) 
{ 
    SomeLogger.log(...); 
    rollback(); 
    throw e; 
} 

và trở lại mã này sau, bạn sẽ ngay lập tức nhận ra rằng mã kiểm tra vào thử có thể thất bại mà không cần phải tinh thần phân tích mã để xác định xem nó có thể Thất bại.

Một điều bạn có thể làm là đảm bảo mọi tài nguyên cơ sở dữ liệu đã được phát hành, mặc dù tôi không chắc liệu điều này có thể xảy ra không.

+0

Câu hỏi không liên quan đến việc bắt ngoại lệ (như RuntimeException có thể bị bắt), nhưng về tính thích hợp của việc bắt buộc nó (như việc thêm SQLException vào chữ ký phương thức có lẽ không liên quan hoặc theo câu hỏi, hầu hết các trường hợp, không có gì được thực hiện ngoại trừ rethrowing) – bla

Các vấn đề liên quan