2012-04-17 59 views
5

Tôi đang sử dụng JPA với Hibernate làm nhà cung cấp với các giao dịch được quản lý bởi container (JBoss AS 6.1.0.Final).Xử lý ngoại lệ với JPA + Hibernate

Tôi đang cố gắng thực hiện một số xử lý ngoại lệ chi tiết bởi vì tôi có một hệ thống phân cấp ngoại lệ cụ thể trên ứng dụng của mình để tôi có thể xác định việc cần làm trong mọi tình huống. Vì vậy, tôi đã nghiên cứu hàng giờ và tôi thấy tài liệu mơ hồ và các ví dụ hơi thô vì xử lý ngoại lệ luôn bị bỏ qua "vì mục đích rõ ràng" hoặc là khối try-catch đơn giản xử lý Ngoại lệ e.

Ví dụ, lấy mã này:

public void deleteCompany(ICompany company) throws MyException1, MyException2 { 
    if(entityManager != null){ 
     if(company !=null) { 
      try { 
       ICompany companyReference= entityManager.getReference(Company.class, company.getId()); 
       entityManager.remove(managedCompany); 
       entityManager.flush(); 
      } catch(EntityNotFoundException companyDoesNotExist) { 
       //Wrap & Throw 
      } 
     } else { 
     throw new MyException1("An error occurred while attempting to save a null instance of a company"); 
     } 
    } else { 
     throw new MyException2("The entity manager instance is null"); 
    } 
} 

Khối catch là trống vì đó là nơi tôi bị mắc kẹt ... Tôi không biết đó là ngoại lệ tôi nên bắt để cảnh báo hệ thống mà người dùng đang cố xóa một bản ghi không tồn tại.

Câu hỏi cụ thể của tôi là: Tôi có thể bắt ngoại lệ Hibernate trên khối catch đó hoặc tôi có phải bắt các JPA không? Tôi tìm thấy một số nguồn cho rằng JPA kết thúc tốt đẹp các trường hợp ngoại lệ của các nhà cung cấp nhưng điều đó nghe có vẻ kỳ quặc đối với tôi. Tôi cũng thấy rằng việc gọi phương thức flush() làm cho nó có thể nắm bắt các ngoại lệ truy cập và thao tác cơ sở dữ liệu, vì các giao dịch được quản lý bởi thùng chứa và do đó cam kết đi kèm thêm các bước sau khi gọi lệnh deleteCompany.

Cảm ơn bạn.

CHỈNH SỬA: Tôi đang bao gồm các trường hợp ngoại lệ được ghi chú bằng @ApplicationException (rollback = true), vì vậy tôi có thể ném lại và xử lý chúng rõ ràng hơn.

CHỈNH SỬA 2: Tôi đã cập nhật mã của mình. Việc hợp nhất trước khi xóa vẫn tồn tại nếu công ty không có trong cơ sở dữ liệu, khiến cho việc xóa thành công mọi lúc. Bây giờ các trường hợp ngoại lệ đang được ném và tôi đang thử nghiệm nó hoạt động như thế nào trong các tình huống khác nhau bắt các ngoại lệ JPA như được gợi ý bởi Nhận thức.

CHỈNH SỬA 3: Bây giờ nó hoạt động !, hóa ra lỗi một phần trong mã của tôi vì cuộc gọi hợp nhất đó. Lấy tham chiếu đầu tiên và cố gắng loại bỏ sau khi thực hiện thủ thuật, theo cách đó tôi có thể bắt được một EntityNotFoundException, quấn nó và ném nó một lần nữa.

Trả lời

5

Bạn chắc chắn sẽ không bắt được ngoại lệ của nhà cung cấp bởi vì chúng bị cuốn vào ngoại lệ JPA. Lưu ý rằng bạn có thể nhận được một trong những loại ngoại lệ tại điểm trong câu hỏi:

  • IllegalArgumentException - cho ở riêng lẻ hoặc các đối tượng phi thực thể
  • IllegalStateException - quản lý thực thể đã bị đóng
  • PersistenceException - ít nhất, một số phân lớp của chúng. Bạn có thể nhận này cho bất kỳ số lý do, nếu không có giao dịch liên quan đến và cuộc gọi đòi hỏi một, nếu một hạn chế cơ sở dữ liệu từ chối hoạt động , nếu giao dịch mất nhiều thời gian vv vv

Bạn thực sự không nên bắt những ngoại lệ này ở mức thấp như vậy, trừ khi bạn đang có kế hoạch tái bọc chúng trong một ngoại lệ ứng dụng tùy chỉnh của một số loại. Nếu bạn quyết định đi tuyến đường đó, hãy đảm bảo bọc ngoại lệ ban đầu, để dấu vết ngăn xếp không bị mất.

Thật đáng lưu ý rằng tất cả ngoại lệ được tạo bởi Trình quản lý thực thể JPA là ngoại lệ thời gian chạy.

+0

Mẹo hay mà bạn cung cấp ở đây, tôi không biết rằng tất cả chủ đề là ngoại lệ thời gian chạy, nhưng âm thanh suy nghĩ hợp lý về các giao dịch được quản lý bởi container và liên quan đến rollback. Tôi sẽ bắt chúng và bọc chúng trong trường hợp ngoại lệ của riêng tôi để ném chúng lên một lần nữa nhưng tôi cũng sẽ bảo tồn ngoại lệ ban đầu. Chỉ một điều ... liệu tôi có thể xác định ngoại lệ cụ thể nếu tôi bắt được PersistenceException không? hoặc là nhận dạng này một cách tiếp cận xấu? – Gamb

+1

Bạn * có thể * lấy ngoại lệ của nhà cung cấp (nó sẽ được bao bọc trong ngoại lệ kiên trì là 'nguyên nhân'), nhưng không phải là một ý tưởng hay vì nhiều lý do. 1) Bạn không nên quan tâm đến nhà cung cấp, bạn muốn có thể thay đổi nhà cung cấp theo ý muốn mà không thay đổi mã của bạn. 2) Việc triển khai của nhà cung cấp không phải lúc nào cũng được ghi nhận đầy đủ, vì vậy việc cố gắng xác định tập hợp đầy đủ các ngoại lệ có thể là một bài tập vô ích. – Perception

+0

Tôi hiểu. Xin lỗi để làm phiền, nhưng tôi vẫn không thấy làm thế nào tôi sẽ có thể xác định nếu một đối tượng không được lưu trữ trong cơ sở dữ liệu khi tôi gọi phương pháp này ... Tôi tìm thấy [trang web này] (http: //www.objectdb .com/api/java/jpa/exceptions) được cho là liệt kê tất cả các ngoại lệ JPA và một trường hợp có vẻ phù hợp với tình trạng khó xử của tôi là javax.persistence.EntityNotFuundException, nhưng nó không rõ ràng nếu nó sẽ được ném bởi một entityManager.remove() gọi ... – Gamb