对不起,这个问题的标题不好,没想到会更好的。
无论如何,我的表格是标签-帖子标签-帖子。 Poststags是一个多对多关系的连接表。我需要选择所有具有给定标签的帖子,我不知道用户将选择搜索多少个标签。我发现执行此操作的一种方法是在下面的代码中,但是我需要循环用户提供的所有标签,并从那里构造查询字符串,因为标签的数量未知。对我来说似乎是一个非常糟糕的解决方案。
另一种解决方案是将所有标签作为纯字符串存储在Posts表的一列中,但是由于其他应用程序要求,我不想这样做。
我有一个有效的sql查询,因为我在尝试在休眠模式下实现之前尝试过纯sql,但是我不喜欢选择包含每个标记的所有帖子,然后加入每个查询,因此有一种方法可以指定同一列多次在WHERE子句中? pt.tag_id = x AND pt.tag_id = y沿线? (我知道这行不通)。 IN运算符也不起作用,因为它将为我提供包含任何提供的标签的帖子,而不仅仅是包含所有提供的标签的帖子。
我还将如何在HQL中实现这样的查询(如果甚至支持类似的子查询?)。还是我可以通过标准以某种方式进行管理?还是我必须使用休眠会话的createSQLQuery方法?
SELECT * FROM
( SELECT * FROM posts p
inner join poststags pt on pt.post_id = p.id
WHERE pt.tag_id = 1 ) AS A
INNER JOIN
( SELECT * FROM posts p
inner join poststags pt on pt.post_id = p.id
WHERE pt.tag_id = 2 ) AS B ON A.id = B.id
是的,我知道此查询不会返回Post实体本身,但我以后可以处理。
答案 0 :(得分:0)
对于这种复杂的选择,不要使用休眠或ORM,它可能会起作用,但是效果不好。
您的用例应该通过全文搜索解决,这意味着每个帖子都需要有自己的标签。
我认为让Tag成为实体没有太多价值。只是一个字符串而已。
全文搜索对于数据库来说可能很繁重,一种更好的方法是使用elasticsearch来提供帮助。 Spring与spring-data-elasticsearch集成在一起,使用起来并不难。 Elasyicsearch在免费文本搜索方面非常强大。
答案 1 :(得分:0)
这是一个可以在Hibernate中使用Criteria查询来“解决”的解决方案。
假设您有一个Post实体,一个PostTag和PostTag实体引用了Post(我认为应该提供您提供的示例查询),我相信这样的事情应该可以满足您的要求:< / p>
static DetachedCriteria getPostTagCriteria(String tagString)
{
DetachedCriteria criteria = DetachedCriteria.forClass(PostTag.class, "uniqueName_" + postTagId);
criteria.createAlias("tag", "tag");
criteria.add(Restrictions.eq("tag.tagString", tagString));
criteria.setProjection(Projections.property("postId"));
return criteria;
}
static List<Post> getPosts(List<String> tagStrings)
{
Criteria criteria = getCurrentSession().createCriteria(Post.class, "post");
for(String tagString : tagStrings)
{
criteria.add(Property.forName("post.id").in(getPostTagCriteria(tagString)));
}
List<Post> ret = criteria.list();
return ret;
}
这假设您具有表示Post,PostTag和Tag的合理实体,并且它们都以我在此处完全构成的明显的父/子方式相互引用。
但是,根据您的输入创建多个分离的条件对象的一般想法应该可以解决您的问题。此解决方案还带有与上述SQL复杂性相同的警告。您将为传入的每个标记创建一个子查询。因此,根据索引和表的大小,您可能需要考虑采用其他方法。