这是我的模式x1c 0d1x
我有很多文章包含标题和内容栏,它们与翻译键有一对一的关系。翻译键有很多值(每种语言一个)
我尝试使用Hibernate @Filter从数据库中获取只有一种语言的帖子。
translations键和translations值实体以经典的方式Map。但是translation值不直接Map到post实体(没有外键)
post实体的Map如下所示:
@Entity
@Data
@Table(name = "posts")
@NamedQuery(name = "Post.findAll", query = "SELECT p FROM Post p")
@FilterDef(name = "langfilter", defaultCondition = "language = :langid", parameters = @ParamDef(name = "langid", type = Integer.class))
public class Post implements Identifiable, Serializable {
private static final long serialVersionUID = 1L;
@Column
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer identifier;
// ID of the TranslationKey
@Column
private Integer name;
@OneToMany(fetch = FetchType.EAGER)
@Filter(name = "langfilter")
@JoinColumn(name = "key", referencedColumnName = "name", insertable = false, updatable = false)
@JsonView(View.class)
private List<TranslationValue> nameTranslations;
// Content column is not mapped for testing
}
我用来测试的代码是这样的:
EntityManager entityManagerLocal = entityManagerFactory.createEntityManager();
Session session = entityManagerLocal.unwrap(Session.class);
session.enableFilter("langfilter").setParameter("langid", 3);
System.out.println(session.find(Post.class, 1));
System.out.println(entityManagerLocal.find(Post.class, 1));
生成的SQL查询为:
SELECT p1_0.`identifier`,
p1_0.`name`,
n1_0.`key`,
n1_0.`identifier`,
n1_0.`language`,
n1_0.`value`
FROM `posts` p1_0
LEFT JOIN `translations_values` n1_0
ON p1_0.`name` = n1_0.`key`
WHERE p1_0.`identifier` =?
正如你所看到的,过滤器被完全忽略了。
我哪里做错了?
附加问题:由于关系总是只产生一个结果(或者根本不产生结果),是否可以用@ManyToOneMap它?
我正在使用:spring-boot-starter 3.0.5(Hibernate ORM核心版本6.1.7.Final)
编辑
转换值Map
@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
}
转换键Map
@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
}
2条答案
按热度按时间k97glaaz1#
基本上,
@Filter
和@FilterDef
功能将过滤器定义应用于实体类Map的表的Map列。幸运的是,它也适用于关联表,但需要一些修改。使用
@FilterJoinTable
注解指定关联的过滤器。u0sqgete2#
Hibernate使用不同的抓取策略来检索实体。
在这种情况下,重要的策略是 * 直接获取 * 和 * 实体查询 *。
由于
@Filter
特性的限制,Hibernate只对 * 实体查询 * 应用过滤器。要应用过滤器实体查询策略,应使用。