Hibernate:多对多包含使用条件的特定ID

Hibernate:多对多包含使用条件的特定ID,hibernate,jpa,many-to-many,criteria,Hibernate,Jpa,Many To Many,Criteria,我正在开发一个JPA应用程序,在这些实体之间存在多对多关联问题: 电影 例如,我只想选择包含所有类别列表的电影。在Criteria API中,我可以执行以下操作: List<Category> requiredCategories = ... //from request CriteriaBuilder b = em.getCriteriaBuilder(); CriteriaQuery<Movie> cq = b.createQuery(Movie.class);

我正在开发一个JPA应用程序,在这些实体之间存在多对多关联问题:

电影

例如,我只想选择包含所有类别列表的电影。在Criteria API中,我可以执行以下操作:

List<Category> requiredCategories = ... //from request


CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Movie> cq = b.createQuery(Movie.class);
Root<Movie> r = cq.from(Movie.class);

Expression<Set<Category>> categories = r.get(Movie_.categories);

Predicate predicate = b.and();
for(Category c : requiredCategories) {
    predicate = b.and(predicate, b.isMember(c, categories));
}
这很好,但问题是我必须先从Category表中获取Category对象,然后在isMember函数中使用它。我想以某种方式避免加入类别表

例如:我希望所有电影都有喜剧和幻想类。考虑这些关键字是分类ID。因此,我需要从ID表中提取ID,然后在IsMead函数中使用它们。我希望避免这种情况,因为信息类别\u id已经存储在关联表movie\u category中。 简而言之,我想要类似isMember的东西,但提供Category.id而不是实体


这样的事情可能吗

据我所知,使用JPA内置工具不可能进行这样的查询,因为联接表不能直接访问。但这是可能的:

公共列表getMoviesByCategoriesList类别ID{ int matchTotal=categoryIds.size; FluentQuery query=FluentJPA.SQLMovie movie, 可接合电影类别->{ 丢弃SqlMovieCategory.joinmovie,Movie::getCategories; List movieid=子查询->{ 字符串movieId=movieCategory.getJoined.getId; 字符串catId=movieCategory.getInverseJoined.getId; 选择电影ID; 来自电影分类; 其中categoryId.containscatId; GROUPBYmovieId; HAVINGCOUNTmovieId==matchTotal;//COUNTDISTINCTmovieId; }; 选择电影; 来自电影; 其中movieid.containsmovie.getId; }; 返回query.createQueryem,Movie.class.getResultList; } 这将生成以下SQL:

SELECT t0.* 
FROM t0 
WHERE (t0.id IN (SELECT t1.movie_id 
FROM movie_category t1 
WHERE (t1.CATEGORIES_id IN ?1 ) 
GROUP BY  t1.movie_id  
HAVING (COUNT(t1.movie_id) = ?2) ) )
子查询需要生成和语义。看见
FluentJPA中的多对多语义已被解释。

谢谢您的回答,也很抱歉响应太晚,但有没有办法将FluentQuery用作JPA规范?@t4dohx:我不确定是否理解您的问题。FluentJPA扩展了现有的JPA基础结构,并允许您使用实体编写SQL查询。作为JPA规范使用是什么意思?我的意思是,如果我使用JpaSpecificationExecutor时可以将其转换为规范,因为我希望将其作为条件。JPA及其所有API(包括条件API)不提供对联接表的直接访问。所以你的要求是不可能的。我看过JpaSpecificationExecutor,它有findXXX和count方法。我发布的示例返回一个列表。您打算调用什么JpaSpecificationExecutor API?你想要达到什么目的?如果你只想返回电影列表,你可以按原样使用发布的示例。如果您有另一个[complex]查询,您希望向其中添加一个条件,则需要使用FluentJPA重写它。由于CriteriaAPI不支持这样的复杂查询,FluentJPA无法生成规范。
List<Category> requiredCategories = ... //from request


CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Movie> cq = b.createQuery(Movie.class);
Root<Movie> r = cq.from(Movie.class);

Expression<Set<Category>> categories = r.get(Movie_.categories);

Predicate predicate = b.and();
for(Category c : requiredCategories) {
    predicate = b.and(predicate, b.isMember(c, categories));
}
SELECT t0.* 
FROM t0 
WHERE (t0.id IN (SELECT t1.movie_id 
FROM movie_category t1 
WHERE (t1.CATEGORIES_id IN ?1 ) 
GROUP BY  t1.movie_id  
HAVING (COUNT(t1.movie_id) = ?2) ) )