我有3个表格,分别是"Movies", "Tags">
我的表:
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 |
+---------+---------+
我想找到任何使用一堆标签的电影但是所有的标签都必须包含在所列影片中。例如,如果我想找到一些带有"标签"的电影。和"tag2",则应用程序结果将是"movie1"one_answers"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;
}
任何建议吗?谢谢你。
Edit1:
这个本地SQL命令它解决了我的问题,但我不能将它转换为hibernate。我被困在这里了,有人能帮忙吗?
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的例子,和2id的大小。
如果要连接两个表movie和标记,我建议使用@JoinedTable注释。如果在Movie类中像这样定义联接表:
@ManyToMany
@JoinTable(
name = "movieandtag",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags;
你可以在标签类中设置双向电影引用(这不是强制性的),像下面():
@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();