在日常開發中,如果使用hibernate的話,常常會被hibernate的事務搞得焦頭爛額。今天解決了之前項目中一直存在的問題,記錄一下。
問題描述
有一張表TemplateCopy,如下
public class TemplateCopy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String description;
@OneToMany(mappedBy = "template")
private Set<SubDomainWeightsCopy> subDomainWeights;
@OneToMany(mappedBy = "template")
private Set<QuestionWeightsCopy> questionWeights;
}
關聯了兩張表:
public class SubDomainWeightsCopy {
@JsonIgnore
@Id
@ManyToOne
@JoinColumn(name = "template_id")
private TemplateCopy template;
@Id
@ManyToOne
@JoinColumn(name = "sub_domain_id")
private SubDomainCopy subDomain;
private BigDecimal weights; //權重
private BigDecimal score;
@Data
public static class RelationId implements Serializable {
private Integer template;
private Integer subDomain;
}
}
public class QuestionWeightsCopy implements IWeightsValue {
@JsonIgnore
@Id
@ManyToOne
@JoinColumn(name = "template_id")
private TemplateCopy template;
@Id
@ManyToOne
@JoinColumn(name = "question_id")
private QuestionCopy question;
private BigDecimal weights;
private BigDecimal score;
@Data
public static class RelationId implements Serializable {
private Integer template;
private Integer question;
}
}
簡單的看一下,TemplateCopy中有一堆SubDomainWeightsCopy,和一堆QuestionWeightsCopy,我們在保存TemplateCopy的時候,通常按照如下來保存
1. templateCopy = save(TemplateCopy)
2. QuestionWeightsCopy.setTemplateCopy(templateCopy)
3. save(QuestionWeightsCopy)
4. SubDomainWeightsCopy.setTemplateCopy(templateCopy)
5. save(SubDomainWeightsCopy)
到這就好了,數據庫已經保存了關聯關系。但是,這時候如果返回save好的templateCopy,subDomainWeights和questionWeights將會是null。
問題解決
使用EntityManager的clear方法
- 保存完畢后,執行entityManager.clear();
- 然后再次查詢該對象,即可完整返回該對象。
EntityManager clear的作用?
EntityManager clear方法會清空其關聯的緩存,從而強制在事務中稍后執行新的數據庫查詢。
什么時候使用EntityManager clear
- 在進行批處理時,為了避免巨大的緩存占用內存並因長時間的臟檢查而增加刷新的時間
- 在進行DML或SQL查詢時,它將完全繞過實體管理器緩存。在這種情況下,由於緩存,將不會實際去數據庫查,會直接將緩存返回。所以造成了數據庫已經保存了,但是查出來還是未保存的狀態。這時候需要清除緩存以避免這種不一致。(本案例就是這種情況的實際例子)