2011-12-24 46 views
45

Đây là mã:Tại sao sử dụng thể hiện được trả về sau khi lưu() trên Kho lưu trữ dữ liệu Spring JPA?

@Repository 
public interface AccountRepository extends JpaRepository<Account, Long> {} 

JpaRepository từ dự án Spring liệu JPA.

Đây là mã kiểm tra:

public class JpaAccountRepositoryTest extends JpaRepositoryTest { 
    @Inject 
    private AccountRepository accountRepository; 

    @Inject 
    private Account account; 

    @Test 
    @Transactional 
    public void createAccount() { 
     Account returnedAccount = accountRepository.save(account); 

     System.out.printf("account ID is %d and for returned account ID is %d\n", account.getId(), returnedAccount.getId()); 
    } 
} 

Dưới đây là kết quả:

account ID is 0 and for returned account ID is 1 

Đây là từ CrudReporsitory.save() javadoc:

Tiết kiệm một thực thể nhất định. Sử dụng thể hiện được trả về cho các hoạt động tiếp theo khi thao tác lưu có thể đã thay đổi hoàn toàn cá thể thực thể.

Đây là mã thực tế cho SimpleJpaRepository từ mùa xuân dữ liệu JPA:

@Transactional 
    public T save(T entity) { 
      if (entityInformation.isNew(entity)) { 
        em.persist(entity); 
        return entity; 
      } else { 
        return em.merge(entity); 
      } 
    } 

Vì vậy, câu hỏi là tại sao chúng ta cần phải sử dụng các trường hợp trở lại thay vì một bản gốc? (vâng, chúng ta phải làm điều đó, nếu không chúng ta tiếp tục làm việc với cá thể tách rời, nhưng tại sao)

Phương thức EntityManager.persist() ban đầu sẽ trả về void, vì vậy cá thể của chúng ta được gắn vào ngữ cảnh bền vững. Có một số phép thuật proxy xảy ra trong khi chuyển tài khoản để lưu vào kho lưu trữ không? Có phải đó là giới hạn kiến ​​trúc của dự án JPA Spring Data?

Trả lời

48

Phương thức save(…) của giao diện CrudRepository được cho là trừu tượng chỉ đơn giản là lưu trữ một thực thể bất kể trạng thái của nó. Vì vậy, nó không được trưng ra cửa hàng thực tế cụ thể, ngay cả khi (như trong JPA) giữa các thực thể mới sẽ được lưu trữ và các thực thể hiện có sẽ được cập nhật. Đó là lý do tại sao phương pháp này thực sự được gọi là save(…) không phải create(…) hoặc update(…). Chúng tôi trả lại kết quả từ phương thức đó để thực sự cho phép triển khai cửa hàng trả lại một phiên bản hoàn toàn khác với JPA có khả năng thực hiện khi merge(…) được gọi.

Vì vậy, thông thường, đó là một quyết định của API để được khoan dung về việc triển khai thực tế và do đó thực hiện phương pháp cho JPA như chúng tôi. Không có thêm proxy thực hiện cho các thực thể được thông qua.

+0

Tôi có thể cho rằng an toàn không sử dụng kết quả trả về cho các thực thể mới? – danidacar

+2

Một số tài liệu về trạng thái của đối tượng được trả về ở đâu? Tức là, đôi khi nó trả về các trường được cập nhật (dấu thời gian), đôi khi các trường không được cập nhật từ DB. – mmcrae

9

Bạn đã bỏ lỡ phần thứ hai: nếu thực thể không phải là mới, hãy gọi merge. merge sao chép trạng thái đối số của nó vào thực thể được đính kèm với cùng một ID và trả về thực thể được đính kèm. Nếu thực thể không phải là mới và bạn không sử dụng thực thể được trả về, bạn sẽ thực hiện các sửa đổi đối với một thực thể tách rời.

+0

Có, đồng ý. Ít nhất, trong trường hợp này nó tương thích với EntityManager. Sẽ tốt hơn nếu đổi tên phương thức này thành saveOrMerge()? – akazlou

+0

Còn các thành viên tạm thời của Object thì sao? Trong trường hợp khi nó kết hợp, tôi nhận được một đối tượng thực sự hoàn toàn mới (mà thành thật mà tôi không quan tâm) nhưng tôi mất tất cả các giá trị tạm thời của Object. –

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