使用 JPA 规范无法在多对多关系中找到不具有实体的实体
Cannot find entities not having an entity in a many to many relationship using a JPA Specification
我希望将此查询实现为 Spring 数据存储库的规范:
select * from Parts
where id not in (select partId
from PartsToDeliveries
where deliveryId = 31)
(基本上,找到不属于特定交付的所有零件)
这里是 类:
@Entity
public class Part {
@Id
private Long id;
@ManyToMany
@JoinTable(name = "PartsToDeliveries", joinColumns = {@JoinColumn(name = "partId")}, inverseJoinColumns = @JoinColumn(name = "deliveryId"))
private Set<Delivery> deliveries = new HashSet<>();
}
和
@Entity
public class Delivery {
@Id
private Long id;
@ManyToMany(mappedBy = "deliveries")
private List<Part> parts;
}
填空:
Specification<Part> specification = (root, criteriaQuery, criteriaBuilder) -> {
? _______ ?
}
我根本不知道从哪里开始。
您可以使用 CriteriaAPI
- CriteriaBuilder#not()
和 subquery()
模拟相似的语义
这里有构建类似查询的 SO 示例
JPA 2.0, Criteria API, Subqueries, In Expressions
这是 JPA 文档 http://docs.oracle.com/javaee/6/api/javax/persistence/criteria/CriteriaBuilder.html
类似于:
criteriaBuilder.not(root.get("deliveries").in(notWantedDelivery))
Antoniosss 找到了正确的解决方案(该文档并不是特别有用)。为了完整起见,这里是最终解决方案:
specification = (root, criteriaQuery, criteriaBuilder) -> {
Subquery<Long> subquery = criteriaQuery.subquery(Long.class);
Root<Part> subFrom = subquery.from(Part.class);
Path<Long> deliveryId = subFrom.join("deliveries").get("id");
subquery.select(subFrom.get("id"));
subquery.where(criteriaBuilder.equal(deliveryId, 31l));
Path<Long> id = root.get("id");
return criteriaBuilder.not(criteriaBuilder.in(id).value(subquery));
};
我希望将此查询实现为 Spring 数据存储库的规范:
select * from Parts
where id not in (select partId
from PartsToDeliveries
where deliveryId = 31)
(基本上,找到不属于特定交付的所有零件)
这里是 类:
@Entity
public class Part {
@Id
private Long id;
@ManyToMany
@JoinTable(name = "PartsToDeliveries", joinColumns = {@JoinColumn(name = "partId")}, inverseJoinColumns = @JoinColumn(name = "deliveryId"))
private Set<Delivery> deliveries = new HashSet<>();
}
和
@Entity
public class Delivery {
@Id
private Long id;
@ManyToMany(mappedBy = "deliveries")
private List<Part> parts;
}
填空:
Specification<Part> specification = (root, criteriaQuery, criteriaBuilder) -> {
? _______ ?
}
我根本不知道从哪里开始。
您可以使用 CriteriaAPI
- CriteriaBuilder#not()
和 subquery()
这里有构建类似查询的 SO 示例 JPA 2.0, Criteria API, Subqueries, In Expressions
这是 JPA 文档 http://docs.oracle.com/javaee/6/api/javax/persistence/criteria/CriteriaBuilder.html
类似于:
criteriaBuilder.not(root.get("deliveries").in(notWantedDelivery))
Antoniosss 找到了正确的解决方案(该文档并不是特别有用)。为了完整起见,这里是最终解决方案:
specification = (root, criteriaQuery, criteriaBuilder) -> {
Subquery<Long> subquery = criteriaQuery.subquery(Long.class);
Root<Part> subFrom = subquery.from(Part.class);
Path<Long> deliveryId = subFrom.join("deliveries").get("id");
subquery.select(subFrom.get("id"));
subquery.where(criteriaBuilder.equal(deliveryId, 31l));
Path<Long> id = root.get("id");
return criteriaBuilder.not(criteriaBuilder.in(id).value(subquery));
};