2010-04-10 2 views
9

tôi đã tạo một tên truy vấn bằng ejb để kiểm tra xem tên người dùng có được sử dụng hay không. Khi singleResult là null, sau đó tôi nhận được ngoại lệ sau đây:javax.persistence.NoResultException: getSingleResult() đã không truy xuất bất kỳ thực thể nào

javax.persistence.NoResultException: getSingleResult() did not retrieve any entities 

Nhưng ngoại lệ này là kết quả mà tôi muốn khi tên người dùng là miễn phí.

Đây là mã:

public User getUserByUsername(String username) throws DAOException{ 
    try{ 
     Query q = em.createNamedQuery(User.getUserByUsername); 
     q.setParameter("username", username); 
     return (User) q.getSingleResult(); 
    }catch(Exception e){ 
     throwException(username, e); 
     return null; 
    } 
} 

Có ai biết vấn đề là gì. :(

Tôi muốn trở về null và don t nhận được một ngoại lệ.

Thank you very much

+0

hiển thị truy vấn được đặt tên? – Bozho

Trả lời

27

Bạn dường như rethrow các ngoại lệ trong khối catch của bạn với báo cáo kết quả throwException(username, e);. Nếu bạn mong đợi để có được người dùng hoặc null mà không cần bất kỳ ngoại lệ này nên trông giống như sau:

public User getUserByUsernameOrNull(String username) { 
    try{ 
     Query q = em.createNamedQuery(User.getUserByUsername); 
     q.setParameter("username", username); 
     return (User) q.getSingleResult(); 
    } catch(NoResultException e) { 
     return null; 
    } 
} 
+1

hoàn hảo. Cảm ơn nhiều. –

0

gì phương pháp throwException làm

Có phải ngoại lệ được ném vào trong đó nhưng bạn đang sử dụng thông báo của ngoại lệ trước đó?

8

Sử dụng getResultList thay vào đó và kiểm tra xem List có trống không (có phần tử không). Nếu không, danh sách chứa một phần tử và bạn chỉ cần trả về nó.

+0

Đây phải là câu trả lời ưu tiên, vì nó tránh được khối xử lý ngoại lệ, trong trường hợp này, JPA dường như đã bị chặn khi khách hàng. http://blog.takipi.com/ignore-checked-exceptions-all-the-cool-devs-are-doing-it-based-on-600000-java-projects/ – michaelok

+0

Lớp Iterables của Guava, cụ thể là phương pháp getFirst, cho thấy cách ngoại lệ cho một trường hợp ngoại lệ có thể tránh được: getFirst 'Trả về phần tử đầu tiên trong iterable hoặc defaultValue nếu iterable rỗng. – michaelok

2

Bạn gặp phải hành vi được xác định khi gọi getSingleResult và không tìm thấy mục nhập nào: A NoResultException bị ném. Bạn có thể bắt NoResultException trong điều khoản catch, bởi vì giao dịch sẽ không được đánh dấu là rollback, khi JPA đang ném NoResultException. Hoặc bạn có thể sử dụng getResultList() và kiểm tra nếu kích thước chính xác là "1", vì vậy bạn biết bạn đã tìm thấy người dùng của mình.

Ngoài ra, tôi sẽ không trả lại "[null]" nếu người dùng không tìm thấy, nhưng ném UserNotFoundException đã chọn (được xác định). Nhưng điều này phụ thuộc vào hợp đồng của phương pháp bạn sẽ thực hiện.

+0

Bạn có thể xây dựng trên: "bởi vì nó là runtimeexception" bắt ngoại lệ "sẽ không phù hợp" .. Tại sao không? –

2

Michael nói: "Bạn có thể bắt NoResultException trong điều khoản bắt, vì giao dịch sẽ không được đánh dấu là rollback, khi JPA đang ném NoResultException." Dường như đối với một số triển khai jpa, NoResultException sẽ rollbak giao dịch, vi phạm đặc tả jpa, theo bài viết này: NoResultException marks transaction rollback

+1

Bạn nói đúng, điều này xảy ra trong Glassfish 4.0 – Roland

0

Nếu ứng dụng của bạn sử dụng mùa xuân Roo câu trả lời đã bỏ phiếu nhất không hoạt động: các ngoại lệ được bắt bởi các khía cạnh và bạn không bao giờ có được những mong muốn NoResultException. Cách duy nhất để giải quyết vấn đề là sử dụng getResultList và để kiểm tra không, một hoặc nhiều kết quả trong kết quả List, như đã nêu trong câu trả lời được bình chọn nhiều thứ hai.