如何创建用于查找带有标签的电影的 Hibernate 搜索查询?
Posted
技术标签:
【中文标题】如何创建用于查找带有标签的电影的 Hibernate 搜索查询?【英文标题】:How to Create a Hibernate Search Query for finding Movies with Tags? 【发布时间】:2021-10-06 18:58:15 【问题描述】:我有 3 个表,分别名为“Movies”、“Tags”、“MoviesAndTags”。
我的桌子:
movie table:
+---------+---------+
| Id | Name |
+---------+---------+
| 1 | movie1 |
| 2 | movie2 |
| 3 | movie3 |
+---------+---------+
tag table:
+---------+---------+
| Id | Name |
+---------+---------+
| 10 | tag1 |
| 20 | tag2 |
| 30 | tag3 |
| 40 | tag4 |
+---------+---------+
movieandtag table:
+---------+---------+
| MovieId | TagId |
+---------+---------+
| 1 | 10 |
| 1 | 20 |
| 1 | 30 |
| 1 | 40 |
| 2 | 10 |
| 2 | 20 |
| 3 | 10 |
| 3 | 40 |
+---------+---------+
我想使用一堆标签查找任何电影,但所有标签都必须包含在列出的电影中。比如我想找一些有“tag1”和“tag2”的电影,那么申请结果就是“movie1”和“movie2”。
我尝试了这段代码来获得结果,但它不像我想要的那样工作。
public List<MovieAndTag> findByTag(List<Tag> tags)
Session currentSession = entityManager.unwrap(Session.class);
Query theQuery = currentSession.createQuery("from MovieAndTag where tag_id in :tag_id", MovieAndTag.class);
theQuery.setParameterList("tag_id", tags.stream().map(Tag::getId).collect(Collectors.toList()));
List<MovieAndTag> resultList = theQuery.getResultList();
return (resultList.isEmpty()) ? new ArrayList<MovieAndTag>() : resultList;
有什么建议吗?谢谢。
编辑1:
这个原生 SQL 命令解决了我的问题,但我无法将其转换为休眠模式。我被困在这里,有人可以帮忙吗?
SELECT mt.id, mt.movie_id, mt.tag_id
FROM movie m
LEFT JOIN movie_and_tag mt
ON mt.movie_id=m.id
WHERE mt.tag_id IN (4, 7)
GROUP BY m.id
HAVING COUNT(*) = 2
4 和 7 个标签 ID 示例,以及 2 个 ID 大小。
【问题讨论】:
所以您正在寻找标签的and
,而不是or
,对吧?
我不知道哪个对解决我的问题有好处或有用。
【参考方案1】:
如果你想加入两个表movie和tag,我建议使用@JoinedTable注解。如果您像这样在 Movie 类中定义连接表:
@ManyToMany
@JoinTable(
name = "movieandtag",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags;
您可以在 Tag 类中设置双向电影引用(这不是强制性的),如下所示():
@ManyToMany(mappedBy = "tags")
private Set<Movie> movies;
要检索结果列表,只需连接两个表即可;
List<Tag> tags = new ArrayList<>(); // initialize here
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Movie> criteriaQuery = builder.createQuery(Movie.class);
Root<Movie> movieRoot = criteriaQuery.from(Movie.class);
movieRoot.alias("movies"); // gives alias to movie table
Predicate tagPredicate = movieRoot
.join("tags").get("id")
.in(tags
.stream()
.map(Tag::getId)
.collect(Collectors.toList())
);
criteriaQuery.where(tagPredicate).distinct(true);
// generates typed query:
// select distinct movies
// from Movie as movies inner join movies.tags as generatedAlias0
// where generatedAlias0.id in (30, 40)
TypedQuery<Movie> query = entityManager.createQuery(criteriaQuery);
query.getResultList();
【讨论】:
以上是关于如何创建用于查找带有标签的电影的 Hibernate 搜索查询?的主要内容,如果未能解决你的问题,请参考以下文章
从带有搜索栏的表格单元格创建模式视图时,无法在导航栏中创建后退按钮