【问题标题】:Hibernate @Filter with @Cache not working使用@Cache 休眠@Filter 不起作用
【发布时间】:2017-10-27 11:32:36
【问题描述】:

我有实体 FormTable 与另一个实体 FormInLangagueTable 有一对多关系,我想过滤掉语言实体(基于动态参数),并且返回具有匹配过滤器参数的语言对象列表的最终对象。

我设法通过 @Filter 和 @FilterDef 实现了这一点,它按预期工作,除了缓存没有发生并且数据库得到了命中每个查询 .

我找到了following JIRA issue,看来我不是第一个遇到这个问题的...

我完全迷路了,如何根据动态参数过滤 FormInLangagueTable 的列表,同时保持 2 级缓存?

谢谢!

表格:

@Entity
@Table(name = "FORM")
@FilterDef(name = "userLanguageFilter", parameters = {
        // Set by the dao, to filter out irrelevant captions
        @ParamDef(name = "languageIdParam", type = "short")
})
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class FormTable {
    private Integer formId;

    ...

    /**
     * All the available language translations for the given form, won't be presented in the json response.
     */
    private List<FormInLanguageFactoryTable> formInLanguages;
    /**
     * Manually fetched from {@link #formInLanguages}, the language used
     * <b>specific to the user</b>, will be returned by the json.
     */
    private String specificLanguageCaption;

    @Id
    @Column(name = "_FormId")
    public Integer getFormId() {
        return formId;
    }

    public void setFormId(Integer formId) {
        this.formId = formId;
    }

    /**
     * Get all the form title in the corresponding languages, then filter it only to the current user language.
     * It <b>will not be presented in the final json,
     * but used in {@link #getSpecificLanguageCaption} to get the string, or null if none found.</b>
     */
    @OneToMany
    @JoinColumn(name = "_FormId", referencedColumnName = "_FormId")
    @Filter(name = "userLanguageFilter", condition = "_LanguageId = :languageIdParam")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    @JsonIgnore
    public List<FormInLanguageTable> getFormInLanguages() {
        return formInLanguages;
    }

    public void setFormInLanguages(List<FormInLanguageTable> languageCaption) {
        this.formInLanguages = languageCaption;
    }

    /**
     * Will convert {@link #getFormInLanguages} into a string (the form caption, or null if none found)
     * @return
     */
    @Transient
    @JsonProperty("languageCaption")
    public String getSpecificLanguageCaption() {
        return this.getFormInLanguages().isEmpty() ? null : this.getFormInLanguages().get(0).getCaption();
    }
}

FormInLanguage:

/**
 * The available languages for the given form
 */
@Entity
@Table(name = "FormInLanguage")
@Cache(usage= CacheConcurrencyStrategy.READ_ONLY)
public class FormInLanguageTable {
    private PK id;
    private String caption;

    @EmbeddedId
    @JsonIgnore
    public PK getId() {
        return id;
    }

    public void setId(PK id) {
        this.id = id;
    }

    @Column(name = "Caption")
    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }

    @Embeddable
    public static class PK implements Serializable {
        private Integer formId;
        private Short languageId;

        @Column(name = "_FormId")
        @JsonIgnore
        public Integer getFormId() {
            return formId;
        }

        public void setFormId(Integer formId) {
            this.formId = formId;
        }

        @Column(name = "_LanguageId")
        public Short getLanguageId() {
            return languageId;
        }

        public void setLanguageId(Short formFieldId) {
            this.languageId = formFieldId;
        }
    }
}

【问题讨论】:

    标签: hibernate caching spring-boot filter one-to-many


    【解决方案1】:

    我也有同样的问题。 直到现在,我发现了这个:

    不能将@Filter 和@Cache 集合结合起来 注释。此限制是由于确保一致性和 因为过滤信息没有存储在二级 缓存。

    如果允许对当前过滤的集合进行缓存,则 二级缓存将仅存储整个集合的一个子集。 之后,每个其他 Session 将从 缓存,即使会话级过滤器没有明确 已激活。

    为此,二级集合缓存仅限于 存储整个集合,而不是子集。

    http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#mapping-column-filter

    我还在寻找解决方案...

    【讨论】:

    • 是的,我在发布问题后也发现了这一点,这确实有意义,使用过滤器会创建数据的过滤版本,这意味着它必须存储整个数据集并分别应用过滤器时间,或使用使用的每个过滤器缓存数据集。两者都需要记忆。我发现使用 Spring boot 缓存注释来缓存服务方法 更有效(您还可以更好地控制缓存,也就是何时驱逐,为它注册的标识符等等...)跨度>
    猜你喜欢
    • 2015-10-28
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 2013-09-25
    • 2013-08-03
    • 1970-01-01
    相关资源
    最近更新 更多