2012-02-24 32 views
6

Xin chào, tôi có một DAO đơn giản với chức năng bên dưới.JPA EntityManager persist() khiến đối tượng xuất hiện tách ra ngay cả khi lỗi được ném

public element createElement(Element e){ 

    em.persist(e); 
    em.flush(); 

    return e; 
} 

Bảng Entity có một hạn chế duy nhất trên cặp (loại, giá trị) và tôi có một bài kiểm tra dưới đây:

public void testCreateElement() throws DataAccessException { 
     // Start with empty Element table 

     Element e = new Element(); 
     e.setType(myType.OTHER); 
     e.setValue("1"); 
     dao.createElement(e); 

     e = new Element(); 
     e.setType(MyType.OTHER); 
     e.setValue("1"); 
     try{ 
       // this should violate unique constraint of database. 
       dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 

     e.setValue("2"); 
     try{ 
      // I expect this to work as there is no element with these values. 
      dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 
    } 

lỗi bắt đầu tiên của tôi xảy ra như tôi mong đợi kể từ khi tôi biết rằng tôi m vi phạm ràng buộc, lần thử thứ hai/bắt không nên ném một lỗi đến mức tôi quan tâm, nhưng nó có, những gì tôi nhận được của nó:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mypackage.Element 

Vì vậy, có vẻ như gọi kiên trì() trên " e "mặc dù nó không tồn tại gây ra ngủ đông để nghĩ rằng đó là một thực thể tách rời. Điều này gây phiền toái vì các chức năng này đang được sử dụng bởi giao diện người dùng JSF đang xử lý ngoại lệ ConstraintViolation, nhưng cố ý giữ đối tượng để người dùng có thể thay đổi một trong các trường và thử lại, và họ nhận được lỗi thực thể tách rời.

Hành vi này có phải là lỗi hibernate vì tôi không nghĩ rằng nó nên làm điều này thực sự? Có cách nào xung quanh điều này ở cấp độ DAO vì vậy mà vẫn tồn tại, t đối xử với đối tượng của tôi như tách ra nếu nó không thực sự tồn tại?

Kính trọng,

Glen x

+0

Chỉ dành cho nụ cười, điều gì sẽ xảy ra nếu bạn tạo một Phần tử mới và đặt các giá trị thích hợp trước lần tạo mới nhất mà bạn đang gọi? –

+0

Nó ổn. – Link19

+0

Điều đó có hữu ích không? Nếu không, điều này có thể làm việc ... e.setValue (1); e = dao.createElement (e); (<- sẽ thất bại) nhưng sau đó e.setValue (2); edao.createElement (e); (<- sẽ làm việc, hy vọng). –

Trả lời

3

Một ngoại lệ ném bởi Hibernate là không thể phục hồi. Điều duy nhất bạn nên làm khi một ngoại lệ như vậy xảy ra là khôi phục giao dịch và đóng phiên. Trạng thái của phiên (và các thực thể của nó) sau một ngoại lệ như vậy là không ổn định.

Nếu bạn muốn giữ một bản sao của phần tử không bị ảnh hưởng, hãy sử dụng merge() thay vì persist() hoặc sao chép phần tử trước khi lưu giữ nó. Lưu ý rằng ngoại lệ được mong đợi, kể từ khi Hibernate vẫn tồn tại và xóa thực thể, nó bắt đầu bằng cách tạo một ID và gán ID cho thực thể, sau đó chèn hàng, gây ra ngoại lệ. Vì vậy, sau khi ngoại lệ, thực thể có một ID được gán, và do đó được coi là một thực thể tách rời bởi Hibernate. Bạn có thể thử đặt lại ID thành null và xem nó có hoạt động hay không, nhưng tôi muốn nhân bản thực thể trước hoặc sử dụng hợp nhất.

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