2015-01-26 15 views
15

Tôi có một JpaRepository kiên trì thực thể mới được tạo ra trong ứng dụng Spring MVC. thực thể này trông như thế này (rất đơn giản):JpaRepository lưu trữ đối tượng mới được tạo. Làm thế nào để làm mới nó?

@Entity 
public class Translation { 

    ..... 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Version version; 

    .... 

} 

và phiên bản thực thể:

@Entity 
public class Version { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "id") 
    private long id; 

    @Column(name = "name") 
    private String name; 

    @Column(name = "version_code") 
    private long code; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "version", cascade = {CascadeType.ALL}, orphanRemoval = true) 
    private Set<Translation> translations; 

} 

tôi tạo ra một đối tượng dịch như

  TranslationDTO t = new TranslationDTO(); 
      t.setText(translationText); 
      ClientVersionDTO version = new ClientVersionDTO(); 
      version.setId(11); 
      t.setVersion(version); 
này

nơi 11 là một phiên bản tồn tại trong cơ sở dữ liệu đã có ngay từ đầu. Xin lưu ý rằng tôi không đặt giá trị cho namecode của ClientVersionDTO.

Sau đó, tôi có một dịch vụ mà vẫn tồn tại đối tượng mới (tôi sử dụng dozer thư viện để chuyển đổi DTO cho các tổ chức)

@Service 
@Transactional 
public class TranslationsServiceImpl implements TranslationsService { 
    @Override 
    public Long create(TranslationDTO translationDTO) { 
     Translation translation = translationsConverter.unconvert(translationDTO); 
     Translation t = translationRepository.saveAndFlush(translation); 

     Translation t2 = translationRepository.findOne(t.getId()); 

     // !!!! t2.getVersion() returns version where no values are set to 'code' and 'name' 

     return t2.getId(); 
    } 
} 

Xin lưu ý nhận xét của tôi "t2.getVersion() trả về phiên bản mà không có giá trị được đặt là ' code 'và' name '"- Tôi đã mong đợi khi tôi lấy dữ liệu từ cơ sở dữ liệu, tôi sẽ nhận được một đối tượng Version ngay từ cơ sở dữ liệu với các giá trị codename được đặt. Tuy nhiên chúng không được thiết lập. Vì vậy, về cơ bản những gì tôi nhận được như một đối tượng t2.getVersion() là đối tượng tương tự như trong đối số đầu vào translationDTO.getVersion(). Làm thế nào tôi có thể làm mất hiệu lực đối tượng Version?

CẬP NHẬT đã thử di chuyển @Transactional sang JpaRepository, nhưng vẫn có cùng kết quả.

+0

Bạn có thể có nghĩa là "Spring MVC"? Đó là bởi vì bạn đã viết "Sprint MVC" – AlexR

+0

Vâng, cảm ơn. Sửa lỗi chính tả. –

+0

Hãy thử di chuyển @Transactional của bạn đến kho lưu trữ của bạn để kiểm tra –

Trả lời

26

Nếu bạn đang sử dụng Hibernate, đây là kết quả mong đợi. Khi bạn gọi translationRepository.saveAndFlush(translation)translationRepository.findOne(t.getId()) cái khác, chúng sẽ nhấn cùng một phiên Hibernate duy trì bộ nhớ cache của tất cả các đối tượng mà nó đã làm việc. Do đó, cuộc gọi thứ hai chỉ đơn giản trả về đối tượng được truyền cho giá trị đầu tiên. Không có gì trong hai dòng đó sẽ buộc Hibernate bắn một truy vấn SELECT trên cơ sở dữ liệu cho thực thể Version.

Hiện tại, thông số JPA có phương thức refresh trên giao diện EntityManager. Thật không may, dữ liệu Spring JPA không hiển thị phương thức này bằng cách sử dụng giao diện JpaRepository của nó. Nếu phương pháp này có sẵn, bạn có thể đã thực hiện t = translationRepository.saveAndFlush(translation) và sau đó versionRepository.refresh(t.getVersion()) để buộc nhà cung cấp JPA đồng bộ hóa thực thể phiên bản với cơ sở dữ liệu.

Triển khai phương pháp này không khó. Chỉ cần mở rộng SimpleJpaRepository lớp từ JPA dữ liệu mùa xuân và tự triển khai phương pháp. Để biết chi tiết, hãy xem adding custom behaviour to all Spring Data JPA repositories.

Cách thay thế sẽ là tải đối tượng phiên bản là versionRepository.findOne(version.getId()) trước khi đặt nó trên bản dịch. Vì bạn có thể mã hóa mã phiên bản cứng trong mã của mình, các phiên bản của bạn dường như là tĩnh. Do đó, bạn có thể đánh dấu thực thể Version của mình là @Immutable@Cacheable (trước đây là chú thích dành riêng cho Hibernate). Bằng cách đó, versionRepository.findOne(version.getId()) không được nhấn vào cơ sở dữ liệu mỗi lần được gọi.

+0

cảm ơn, thực sự tôi cũng đã đi vào kết luận và sử dụng phương pháp thứ hai. Btw, phiên bản không bị bẻ khóa, nó ở đây chỉ để đơn giản. –

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