我已经构建了一个可标记文档列表,标记与文档之间存在多对多关系。我现在想使用hibernate标准机制查询每个标记的“摘要”,其中包括特定标记的使用频率计数,以及对文档是否已发布的额外限制。
我正在使用的实体大致如下(你会在中间注意到一个SQL连接表):
@Entity
public class DocumentTag {
... various things ...
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "tags")
private List<Document> documents = new ArrayList<>();
}
@Entity
public class Document {
... various things ...
@Basic
@Column(name = "published", columnDefinition = "BIT", length = 1)
protected boolean published = false;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "document_tag_joins",
uniqueConstraints = @UniqueConstraint(
columnNames = {"document", "tag"}
),
joinColumns = {@JoinColumn(name = "document")},
inverseJoinColumns = {@JoinColumn(name = "tag")})
private List<DocumentTag> tags = new ArrayList<>();
}
鉴于上述情况,我已经设法弄清楚构建查询应该或多或少地起作用如下:
Criteria c = session.createCriteria(DocumentTag.class);
c.createAlias("documents", "docs",
JoinType.LEFT_OUTER_JOIN,
Restrictions.eq("published", true)
);
c.setProjection(
Projections.projectionList()
.add(Projections.alias(Projections.groupProperty("id"), "id"))
.add(Projections.alias(Projections.property("createdDate"), "createdDate"))
.add(Projections.alias(Projections.property("modifiedDate"), "modifiedDate"))
.add(Projections.alias(Projections.property("name"), "name"))
.add(Projections.countDistinct("docs.id"), "documentCount"));
// Custom response entity mapping
c.setResultTransformer(
Transformers.aliasToBean(DocumentTagSummary.class)
);
List<DocumentTagSummary> results = c.list();
鉴于上述情况,hibernate生成的SQL查询如下所示:
SELECT
this_.id AS y0_,
this_.createdDate AS y1_,
this_.modifiedDate AS y2_,
this_.name AS y3_,
count(DISTINCT doc1_.id) AS y5_
FROM tags this_
LEFT OUTER JOIN tag_joins documents3_
ON this_.id = documents3_.tag AND (doc1_.published = ?)
LEFT OUTER JOIN documents doc1_
ON documents3_.document = doc1_.id AND (doc1_.published = ?)
GROUP BY this_.id
如上所示,发布约束适用于两个左外连接。我不确定这是否是设计的,但我需要的是将已发布的约束仅应用于第二个左外连接。
有什么想法吗?
答案 0 :(得分:0)
我能够通过侧身来避开这个问题。首先,我必须更改“已发布”列以使用整数而不是一点。然后我能够稍微修改结果的投影,如下所示:
// Start building the projections
ProjectionList projections =
Projections.projectionList()
.add(Projections.alias(
Projections.groupProperty("id"), "id"))
.add(Projections.alias(
Projections.property("createdDate"),
"createdDate"))
.add(Projections.alias(
Projections.property("modifiedDate"),
"modifiedDate"))
.add(Projections.alias(
Projections.property("name"), "name"));
if (isAdmin()) {
// Give the raw count.
projections.add(Projections.countDistinct("docs.id"), "documentCount");
} else {
// Use the sum of the "published" field.
projections.add(Projections.sum("docs.published"), "documentCount");
}
我承认这实际上并没有回答关于为什么多对多表上的hibernate条件约束被应用于所有表的问题,但它解决了我的问题。