Hibernate @Filter注解失效排查及多语言映射优化咨询
补充实体映射
TranslationValue实体
@Entity @Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "translations_values") @NamedQuery(name = "TranslationValue.findAll", query = "SELECT t FROM TranslationValue t") public class TranslationValue implements Identifiable, Serializable { private static final long serialVersionUID = 1L; @Column(name = "identifier") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonView(View.class) private Integer identifier; @Column(name = "key", insertable = false, updatable = false) private Integer keyIdentifier; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "key") private TranslationKey key; @Column(name = "language", insertable = false, updatable = false) private Integer languageIdentifier; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "language") private Language language; @Column(name = "value") @Lob private String value; // Getters & Setters }
TranslationKey实体
@Entity @Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "translations_keys") @NamedQuery(name = "TranslationKey.findAll", query = "SELECT t FROM TranslationKey t") public class TranslationKey implements Identifiable, Serializable { private static final long serialVersionUID = 1L; @Column(name = "identifier") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer identifier; @CriteriaParticipant @Column(name = "constraint") private Integer metadata; @OneToMany(mappedBy = "key") @Fetch(FetchMode.SELECT) @BatchSize(size = 1000) private List<TranslationValue> values; // Getters and Setters }
解决方案
问题1:@Filter未生效的修复
你把@FilterDef定义在了Post实体上,但过滤条件中的language字段属于TranslationValue实体,Hibernate无法在Post的上下文里识别这个字段,导致过滤器失效。
正确修改方式:
- 移除
Post实体上的@FilterDef,将其移到TranslationValue实体,并直接在该实体上定义过滤条件:
@Entity @Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "translations_values") @NamedQuery(name = "TranslationValue.findAll", query = "SELECT t FROM TranslationValue t") @FilterDef(name = "langfilter", parameters = @ParamDef(name = "langid", type = Integer.class)) @Filter(name = "langfilter", condition = "language = :langid") public class TranslationValue implements Identifiable, Serializable { // 其他代码保持不变 }
- 在
Post实体的nameTranslations关联上,保留@Filter注解引用该过滤器:
@OneToMany(fetch = FetchType.EAGER) @Filter(name = "langfilter") @JoinColumn(name = "key", referencedColumnName = "name", insertable = false, updatable = false) @JsonView(View.class) private List<TranslationValue> nameTranslations;
修改后,Hibernate会在关联查询TranslationValue时自动应用过滤条件,生成的SQL会带上language = 3的限制。
注意:Hibernate 6+版本要确保过滤器参数类型和实体字段类型严格匹配,这里language是Integer类型,参数配置正确。
问题2:是否可以用@ManyToOne映射
完全可以。因为每个帖子对应一个翻译键,而指定语言下每个翻译键只会有一条翻译值,所以可以将nameTranslations从List<TranslationValue>改为TranslationValue,并使用@ManyToOne映射,配合过滤器获取指定语言的翻译值:
修改后的Post实体关联代码:
@ManyToOne(fetch = FetchType.EAGER) @Filter(name = "langfilter") @JoinColumn(name = "name", referencedColumnName = "key", insertable = false, updatable = false) @JsonView(View.class) private TranslationValue nameTranslation;
这种映射更贴合你的业务场景,查询时只会加载对应语言的那一条翻译值(返回一个或零个结果)。
内容的提问来源于stack exchange,提问作者Emax
相关产品推荐
相关产品推荐

