多对多关系中的JPA条件查询

多对多关系中的JPA条件查询,jpa,eclipselink,criteria,jpql,criteria-api,Jpa,Eclipselink,Criteria,Jpql,Criteria Api,我在EclipseLink 2.3.2中使用JPA 2.0,在该版本中,产品和颜色之间存在多对多关系。一种产品可以有多种颜色,一种颜色可以与多种产品相关联。该关系在数据库中由三个表表示 产品 产品颜色连接表 颜色 prod_COLOR表有两个参考列prod_id和COLOR_id,分别来自其相关父表product和COLOR 显而易见,实体类产品有一组颜色-java.util.set,名为colorset 实体类color有一组产品-java.util.set,名为productSet 我需要根

我在EclipseLink 2.3.2中使用JPA 2.0,在该版本中,产品和颜色之间存在多对多关系。一种产品可以有多种颜色,一种颜色可以与多种产品相关联。该关系在数据库中由三个表表示

产品 产品颜色连接表 颜色 prod_COLOR表有两个参考列prod_id和COLOR_id,分别来自其相关父表product和COLOR

显而易见,实体类产品有一组颜色-java.util.set,名为colorset

实体类color有一组产品-java.util.set,名为productSet

我需要根据提供的prodId从颜色表中获取颜色列表,该列表与prod_颜色表中的颜色不匹配

相应的JPQL如下所示

从颜色 color.colorID在哪里 不在 选择颜色 来自产品 内部连接产品。颜色设置颜色 其中product.prodId=:id 按颜色订购 它生成以下SQL语句

选择t0.color\u id、t0.color\u hex、t0.color\u name 从projectdb.color t0 其中t0.color\u id 不在 选择不同的t1.COLOR\U id 来自prod_colour t3、projectdb.product t2、projectdb.colour t1 其中t2.prod_id=? t3.prod_id=t2.prod_id t1.color\u id=t3.color\u id 按t0订购。颜色\u id说明 因为这将是一个运行时查询,所以最好有一个条件查询。我不知道如何在这种复杂的关系中构造条件查询

到目前为止,我有以下查询,它与前面的JPQL完全无关

CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Colour>criteriaQuery=criteriaBuilder.createQuery(Colour.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Colour> entityType = metamodel.entity(Colour.class);
Root<Colour> root = criteriaQuery.from(entityType);
SetJoin<Colour, Product> join = root.join(Colour_.productSet, JoinType.INNER);
ParameterExpression<Long> parameterExpression=criteriaBuilder.parameter(Long.class);
criteriaQuery.where(criteriaBuilder.equal(join.get(Product_.prodId), parameterExpression));  

TypedQuery<Colour> typedQuery = entityManager.createQuery(criteriaQuery).setParameter(parameterExpression, prodId);
List<Colour> list=typedQuery.getResultList();
如何将此查询与子查询关联,以便生成以下SQL查询

选择t0.color\u id、t0.color\u hex、t0.color\u name 从projectdb.color t0 其中t0.color\u id 不在 选择t0.COLOR\U id 来自projectdb.color t0、prod_color t2、projectdb.product t1 其中t1.prod_id=1 t2.color\u id=t0.color\u id t1.prod_id=t2.prod_id 按t0订购。颜色\u id说明 编辑:

以下条件查询与不存在一起工作

这应该是这样的,

选择t0.color\u id、t0.color\u hex、t0.color\u name 从projectdb.color t0 哪里 不存在 选择t0.COLOR\U id 来自产品颜色t3,项目数据库产品t2 其中t2.prod_id=1 t3.color\u id=t0.color\u id t2.prod_id=t3.prod_id 按t0订购。颜色\u id说明 有并没有一种方法可以让子查询使用NOT IN子句而不是NOT EXISTS,并消除这种冗余连接


此查询生成的冗余联接已报告为。

以下是有关NOT IN I的条件查询,但是,与NOT IN相比,首选NOT EXISTS

此查询返回所需的结果集。然而,它产生了一个冗余连接,这可以看出,但这似乎是一个错误

编辑:

在Hibernate上尝试时,编写此条件查询的方式看起来不正确。联接和子查询的组合可以生成正确的SQL查询

CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Colour>criteriaQuery=criteriaBuilder.createQuery(Colour.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Colour> entityType = metamodel.entity(Colour.class);
Root<Colour> root = criteriaQuery.from(entityType);
criteriaQuery.select(root);

Subquery<Long>subquery=criteriaQuery.subquery(Long.class);
Root<Colour> subRoot = subquery.from(Colour.class);
subquery.select(subRoot.get(Colour_.colourId));
SetJoin<Colour, Product> join = subRoot.join(Colour_.productSet, JoinType.INNER);

ParameterExpression<Long> parameterExpression=criteriaBuilder.parameter(Long.class);
criteriaQuery.where(criteriaBuilder.in(root.get(Colour_.colourId)).value(subquery).not());
subquery.where(criteriaBuilder.equal(join.get(Product_.prodId), parameterExpression));
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Colour_.colourId)));

TypedQuery<Colour> typedQuery = entityManager.createQuery(criteriaQuery);
List<Colour> list = typedQuery.setParameter(parameterExpression, 1L).getResultList();
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Colour>criteriaQuery=criteriaBuilder.createQuery(Colour.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Colour> entityType = metamodel.entity(Colour.class);
Root<Colour> root = criteriaQuery.from(entityType);
criteriaQuery.select(root);
Subquery<Long>subquery=criteriaQuery.subquery(Long.class);
Root<Product> subRoot = subquery.from(Product.class);
subquery.select(root.get(Colour_.colourId));
Predicate paramPredicate = criteriaBuilder.equal(subRoot.get(Product_.prodId), prodId);
Predicate correlatePredicate = criteriaBuilder.equal(root.get(Colour_.productSet), subRoot);
subquery.where(criteriaBuilder.and(paramPredicate, correlatePredicate));
criteriaQuery.where(criteriaBuilder.exists(subquery).not());
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Colour_.colourId)));

TypedQuery<Colour> typedQuery = entityManager.createQuery(criteriaQuery);
List<Colour>list= typedQuery.getResultList();
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Colour>criteriaQuery=criteriaBuilder.createQuery(Colour.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Colour> entityType = metamodel.entity(Colour.class);
Root<Colour> root = criteriaQuery.from(entityType);
criteriaQuery.select(root);

Subquery<Long>subquery=criteriaQuery.subquery(Long.class);
Root<Product> subRoot = subquery.from(Product.class);
subquery.select(root.get(Colour_.colourId));

Predicate paramPredicate = criteriaBuilder.equal(subRoot.get(Product_.prodId), prodId);
Predicate correlatePredicate = criteriaBuilder.equal(root.get(Colour_.productSet), subRoot);

subquery.where(criteriaBuilder.and(paramPredicate, correlatePredicate));
criteriaQuery.where(criteriaBuilder.in(root.get(Colour_.colourId)).value(subquery).not());
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Colour_.colourId)));

TypedQuery<Colour> typedQuery = entityManager.createQuery(criteriaQuery);
List<Colour> list=typedQuery.getResultList();
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Colour>criteriaQuery=criteriaBuilder.createQuery(Colour.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Colour> entityType = metamodel.entity(Colour.class);
Root<Colour> root = criteriaQuery.from(entityType);
criteriaQuery.select(root);

Subquery<Long>subquery=criteriaQuery.subquery(Long.class);
Root<Colour> subRoot = subquery.from(Colour.class);
subquery.select(subRoot.get(Colour_.colourId));
SetJoin<Colour, Product> join = subRoot.join(Colour_.productSet, JoinType.INNER);

ParameterExpression<Long> parameterExpression=criteriaBuilder.parameter(Long.class);
criteriaQuery.where(criteriaBuilder.in(root.get(Colour_.colourId)).value(subquery).not());
subquery.where(criteriaBuilder.equal(join.get(Product_.prodId), parameterExpression));
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Colour_.colourId)));

TypedQuery<Colour> typedQuery = entityManager.createQuery(criteriaQuery);
List<Colour> list = typedQuery.setParameter(parameterExpression, 1L).getResultList();