2012-02-03 22 views
5

Tôi có một ứng dụng sandbox Seam 3 sử dụng JBoss 7, Hibernate như thực hiện JPA mặc định và JSF làm giao diện người dùng web.JPA/Hibernate phát ra không có CẬP NHẬT trên cam kết trong môi trường EJB/Seam

Tôi gặp sự cố, rằng UPDATE SQL bị nuốt theo mặc định.

EJB stateful của tôi trong phạm vi trò chuyện duy trì một mở rộng scoped EntityManager và một Entity, container Giao dịch Managed (Yêu cầu mới)

  1. Các EntityManager được tiêm
  2. EJB sử dụng EM để nạp Entity và giữ nó trong một lĩnh vực
  3. ứng dụng JSF truy cập vào EJB và thực thể của nó, thay đổi một lĩnh vực Chuỗi
  4. Calles ứng dụng JSF phương pháp "Save" trong EJB
  5. trong save() Tôi kiểm tra, nếu trường Thực thể đã được thay đổi -> nó đã được thay đổi đúng cách
  6. Tôi không làm gì nữa, vùng chứa cam kết giao dịch sau khi lưu() xong.
  7. Vấn đề: Không cập nhật SQL nào được thực hiện đối với DB.

Nếu tôi mở rộng lưu() bằng cách:

a) entityManager.contains (thực thể) UPDATE được thực hiện như mong đợi (kết quả là "true")

HOẶC

b) entityManager.persist (thực thể) UPDATE được thực hiện như mong đợi

Q: Theo tôi hiểu các thông số không phải là a) hoặc b) phải được yêu cầu, vì thực thể vẫn được quản lý trong toàn bộ quá trình. Tôi không hiểu, tại sao a) có tác dụng tiết kiệm. Tôi có thể chụp ảnh b) có tác dụng tiết kiệm, nhưng không cần thiết, phải không?

Mọi lời giải thích đều được hoan nghênh.

Đây là EJB của tôi:

@Named 
@ConversationScoped 
@Stateful 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public class LanguageBean { 

    @PersistenceContext(type = PersistenceContextType.EXTENDED) 
    private EntityManager em; 
    @Inject 
    private UserTransaction transaction; 

    private Language value; 

    @Inject 
    Conversation conversation; 

    public LanguageBean() { 
     super(); 
    } 

    @Begin 
    public void selectLanguage(Long anId) { 
     conversation.setTimeout(10 * 60 * 1000); 
     if (anId != null) { 
      value = em.find(Language.class, anId); 
     } 
    } 

    @BeforeCompletion 
    public void transactionComplete(){ 
     System.out.println("transactionComplete"); 
    } 

    public Language getValue() { 
     return value; 
    } 

    @Produces 
    @Named 
    @ConversationScoped 
    public Language getLanguage() { 
     return getValue(); 
    } 

    public void setValue(Language aValue) { 
     value = aValue; 
    } 

    @End 
    public String save() { 
//  displays the changed attribute: 
     System.out.println("save code: "+value.getCode()); 

//  why is either this required: 
//  boolean tempContains = em.contains(value); 
//  System.out.println("managed: "+tempContains); 

//  or: why is persist required: 
     em.persist(value); 
     return "languages?faces-redirect=true"; 
    } 

    @End 
    public String cancel() throws SystemException { 
     transaction.setRollbackOnly(); 
     return "languages?faces-redirect=true"; 
    } 

} 
+0

tôi phát hiện ra entityManager.flush() cũng giải quyết được vấn đề. Nhưng tôi không hiểu tại sao điều này dường như được yêu cầu. Từ thông số JPA: "Khi giao dịch JTA cam kết, nhà cung cấp phải xóa tất cả trạng thái thực thể đã sửa đổi thành cơ sở dữ liệu ". – user1187037

+0

có thể một nơi nào đó phiên FlushMode của phiên ngủ đông được đặt thành không? – Firo

Trả lời

0

Cố gắng thêm @Remove chú thích về phương pháp chú thích bởi @End.

Theo ý kiến ​​của tôi @End chú thích không dẫn đến hủy diệt đậu. Vì vậy, bối cảnh kiên trì đang hoạt động ngay cả sau khi thực thi save() và nội dung của nó không thể được chuyển sang cơ sở dữ liệu.

1

Trải nghiệm của tôi chủ yếu là với đường nối 2 nhưng phải được áp dụng như nhau ở đây.

Cuộc trò chuyện và phiên JPA được tách riêng trong đường may vì lý do đơn giản là cuộc trò chuyện kết thúc có thể không dẫn đến việc thực thể được lưu.

Ví dụ, một hành động hủy trên một cuộc trò chuyện dài chạy sẽ kết thúc cuộc nói chuyện (vì không có lý do gì để duy trì cuộc nói chuyện nữa)

Xét rằng bạn đang làm một rollback trên hủy bỏ trong ví dụ của bạn, nó cũng sẽ có vẻ hợp lý mà bạn sẽ cần phải gọi một tuôn ra như đề nghị của @ user1187037 (về mặt lý thuyết một cam kết nhưng tôi không nghĩ rằng đó là cho phép)

Tôi nghĩ rằng có thể có một cấu hình bạn có thể thiết lập để nó đã tuôn ra về cuộc trò chuyện kết thúc nhưng tôi có thể bị nhầm lẫn.

Trong mọi trường hợp, http://javalangblog.blogspot.co.uk/2010/04/flush-mode-conversation.html dường như đề nghị một giải pháp

Hy vọng rằng sẽ giúp.

EDIT: Bạn có thể cấu hình các chế độ tuôn ra mỗi cuộc nói chuyện bằng xml

<begin-conversation join="true" flush-mode="COMMIT" /> 

và sử dụng các chú thích

@Begin(flushMode=COMMIT) 

Gấu nhớ rằng mặc dù một cuộc trò chuyện có thể @end trên mà chưa được định nghĩa một cách rõ ràng. Nếu người dùng đang tham gia cuộc trò chuyện, thực hiện thay đổi đối với các thực thể và sau đó từ bỏ cuộc trò chuyện, người đó sẽ tự động bị đóng sau khi hết thời gian chờ. Nếu tôi nhớ chính xác, điều này sẽ gây ra bất kỳ thay đổi nào để cam kết trong trường hợp trên.

Tài liệu tham khảo:

http://docs.jboss.org/seam/3/persistence/3.0.0.Alpha1/reference/en-US/html_single/#d0e249 http://docs.jboss.org/seam/3/latest/api/org/jboss/seam/persistence/FlushModeType.html