簡體   English   中英

防止 hibernate 實體更改被持久化

[英]Prevent hibernate entity changes from being persisted

I am updating my application from Spring Boot 1.4.5 / Hibernate 4.3.5 to Spring Boot 2.0.9 / Hibernate 5.2.18 and code that used to work in the previous configuration is no longer working.

場景如下:

  1. 通過輸入帶有 @Transactional 注釋的方法來啟動事務
  2. 水合實體
  3. 更改實體
  4. 進行另一個查詢
  5. 發現問題。 由於此問題,請確定更改不應持續存在。
  6. 驅逐實體
  7. 退出方法/事務

在 Hibernate 4.3.5 中,調用 entityManager.detach() 將阻止更改被持久化。 但是,對於 Hibernate 5.2.18,我發現即使使用此調用,更改也會持續存在。 我還嘗試從 session 中驅逐(),並嘗試從 session 中清除()所有實體(只是想看看會發生什么)。

所以我問 - 是否可以像我在 Hibernate 4.3.5 中所做的那樣丟棄 Hibernate 5.2.18 中的實體更改?

相關代碼如下...

@Entity
public class Agreement {

    private Long agreementId;
    private Integer agreementStateId;

    @Id
    @Column(name = "agreement_id")
    public Long getAgreementId() {
        return agreementId;
    }

    public void setAgreementId(Long agreementId) {
        this.agreementId = agreementId;
    }

    @Basic
    @Column(name = "agreement_state_id", nullable = false)
    public Integer getAgreementStateId() {
        return agreementStateId;
    }

    public void setAgreementStateId(Integer agreementStateId) {
        this.agreementStateId = agreementStateId;
    }
}


@Component
public class Repo1 {

    @PersistenceContext(unitName = "rights")
    private EntityManager entityManager;

    public void evict(Object entity) {
        entityManager.detach(entity);
    }

    public Agreement getAgreement(Long agreementId) {
        // Code to get entity is here.
        // Agreement with an agreementStateId of 5 is returned.
    }

    public void anotherQuery() {
        // Code to make another query is here.
    }
}


@Component
public class Service1 {

    @Autowired
    Repo1 repo;

    @Transactional
    public void doSomething() {
        Agreement agreement = repo.getAgreement(1L);

        // Change agreementStateId.  Very simple for purposes of example.
        agreement.setAgreementStateId(100);

        // Make another query
        repo.anotherQuery();

        // Detect a problem here. Simplified for purposes of example.
        if (agreement.getAgreementStateId() == 100) {
            repo.evict(agreement);
        }
    }
}

我發現了問題,它與 evict() 無關。 事實證明,一個額外的查詢導致 session 在 evict() 調用之前刷新。

通常,應用程序使用 QueryDSL 進行查詢。 在進行查詢之前,以這種方式進行的查詢不會導致 session 刷新。 但是在這種情況下,查詢是通過 Session.createSQLQuery() 創建的。 這使用了已分配給 session 的 FlushMode,即 FlushMode.AUTO。

在進行查詢之前,我可以通過在查詢上調用 setHibernateFlushMode(FlushMode.COMMIT) 來防止刷新。 這會導致 session FlushMode 臨時更改,直到運行查詢之后。 之后, evict() 調用按預期工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM