2013-07-17 26 views
42

Tôi có một EJB nơi tôi đang lưu một đối tượng vào cơ sở dữ liệu. Trong một ví dụ tôi đã thấy, một khi dữ liệu này được lưu (EntityManager.persist) có một cuộc gọi đến EntityManager.flush(); Tại sao tôi cần phải làm điều này? Đối tượng tôi đang lưu không được đính kèm và không được sử dụng sau này trong phương thức. Trong thực tế, một khi đã lưu phương thức trả về và tôi mong đợi các tài nguyên được phát hành. (Đoạn mã ví dụ thực hiện điều này trên một cuộc gọi remove là tốt.)EntityManager.flush làm gì và tại sao tôi cần sử dụng nó?

if (somecondition) 
     entityManager.persist(unAttachedEntity); 
    else 
    { 
     attachedEntityObject.setId(unAttachedEntity.getId()); 
    } 
    entityManager.flush(); 

Trả lời

32

Một cuộc gọi đến EntityManager.flush(); sẽ buộc các dữ liệu được tồn tại trong cơ sở dữ liệu ngay lập tức như EntityManager.persist() sẽ không (tùy thuộc vào cách EntityManager được cấu hình: FlushModeType (AUTO hoặc COMMIT) theo mặc định nó được đặt thành AUTO và một lệnh tuôn ra sẽ được thực hiện tự động bởi nếu nó được đặt thành COMMIT, sự kiên trì của dữ liệu vào cơ sở dữ liệu bên dưới sẽ bị trì hoãn khi giao dịch được cam kết).

+5

Mô tả về 'FlushModeType' không đúng: về cơ bản AUTO có nghĩa là nếu bạn thay đổi thực thể và sau đó thực hiện truy vấn SELECT có thể trả về thực thể đó, AUTO sẽ buộc thay đổi đối tượng đó bị xóa trước khi thực thi SELECT. –

14

EntityManager.persist() làm cho thực thể liên tục trong khi EntityManager.flush() thực sự chạy truy vấn trên cơ sở dữ liệu của bạn.

Vì vậy, khi bạn gọi EntityManager.flush(), các truy vấn để chèn/cập nhật/xóa các thực thể liên quan được thực thi trong cơ sở dữ liệu. Bất kỳ lỗi nào về ràng buộc (chiều rộng cột, kiểu dữ liệu, khóa ngoại) sẽ được biết tại thời điểm này.

Hành vi cụ thể phụ thuộc vào việc chế độ xả là AUTO hay COMMIT.

13

Thao tác EntityManager.flush() có thể được sử dụng để ghi tất cả thay đổi vào cơ sở dữ liệu trước khi giao dịch được thực hiện. Theo mặc định, JPA thường không ghi các thay đổi vào cơ sở dữ liệu cho đến khi giao dịch được thực hiện. Điều này thường là mong muốn vì nó tránh truy cập cơ sở dữ liệu, tài nguyên và khóa cho đến khi được yêu cầu. Nó cũng cho phép cơ sở dữ liệu viết được sắp xếp, và theo đợt để truy cập cơ sở dữ liệu tối ưu, và để duy trì các ràng buộc toàn vẹn và tránh deadlocks. Điều này có nghĩa rằng khi bạn gọi kiên trì, hợp nhất hoặc xóa cơ sở dữ liệu DML INSERT, UPDATE, DELETE không được thực hiện, cho đến khi cam kết hoặc cho đến khi kích hoạt được kích hoạt.

+1

Hoạt động EntityManager.flush() có thể được sử dụng để ghi tất cả các thay đổi vào cơ sở dữ liệu trước khi giao dịch được thực hiện. -> Điều này không hoàn toàn đúng. Bạn vẫn cần phải commit, flush chỉ gửi các câu lệnh SQL tới cơ sở dữ liệu KHÔNG CÓ commit. Kích hoạt tuôn ra, không cam kết sẽ không thực sự INSERT bất kỳ thực thể nào. cam kết sẽ tuôn ra cho bạn, nếu bạn chưa flushed, nhưng flush sẽ không cam kết .. –

+0

EntityManager.flush() sẽ gửi dữ liệu đến cơ sở dữ liệu, nhưng nó sẽ không hiển thị cho những người khác tại thời điểm này. Thay vào đó, các mục cơ sở dữ liệu đã thay đổi sẽ nhận được khóa hàng. Nhưng chỉ sau khi commit() các thay đổi sẽ hiển thị với người khác, và các khóa được loại bỏ. – user2081279

8

Vì vậy, khi bạn gọi EntityManager.persist(), nó chỉ làm cho thực thể được quản lý bởi EntityManager và thêm nó (thực thể) vào Persistence Context. An Explicit flush() sẽ làm cho thực thể hiện đang ở trong Persistence Context để được chuyển đến cơ sở dữ liệu (sử dụng SQL).

Nếu không có tuôn ra(), điều này (di chuyển thực thể từ Persistence Context đến cơ sở dữ liệu) sẽ xảy ra khi giao dịch mà liên kết này Persistence Context được liên kết.

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