java - 在 JPA 中对具有多对多关系的对象执行 NOT IN QUERY
问题描述
我有两个 JPA 对象Product
,Order
它们之间有多对多的关系。
@Entity
@Table(name = "orders")
@JsonInclude(NON_NULL)
public class Order implements Serializable {
public static final int PRECISION = 2;
@Id
@GeneratedValue(strategy = IDENTITY)
@JsonIgnore
private String orderId;
@Column(unique = true, nullable = false, length = 8)
private String orderNumber;
@Column
private BigDecimal discount;
@Column(nullable = false)
private BigDecimal taxPercent;
private BigDecimal total;
private BigDecimal totalTax;
private BigDecimal grandTotal;
@Column(length = 10)
private String status;
@ManyToMany(cascade = ALL, fetch = FetchType.EAGER)
@JoinTable(
name = "order_product",
joinColumns = @JoinColumn(name = "order_id", updatable = false, nullable = false),
inverseJoinColumns = @JoinColumn(name = "product_id", updatable = false, nullable = false)
)
private List<Product> products = new ArrayList<>();
public BigDecimal getTotal() {
BigDecimal total = new BigDecimal(ZERO);
if (products == null || products.isEmpty()) {
return total;
}
for (Product product : products) {
total = total.add(product.getPrice());
}
return scaled(total);
}
public BigDecimal getTotalTax() {
return scaled(getTotal().multiply(taxPercent.divide(new BigDecimal("100"))));
}
public BigDecimal getGrandTotal() {
BigDecimal total = this.getTotal().add(getTotalTax());
if (discount != null) {
return scaled(total.subtract(discount));
}
return scaled(total);
}
private BigDecimal scaled(BigDecimal value) {
return value.setScale(PRECISION, ROUND_FLOOR);
}
.. Getters and setters ...
}
和产品
@Entity
@Table(name = "products")
public class Product implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@JsonIgnore
private String productId;
@Column(unique = true, nullable = false, length = 10)
private String upc;
@Column(unique = true, nullable = false, length = 13)
private String sku;
@Column(nullable = false)
private String description;
@Column(nullable = false)
private BigDecimal price;
public BigDecimal getPrice() {
return price;
}
@ManyToMany(mappedBy="products", fetch=FetchType.EAGER)
@JsonIgnore
private List<Order> orders = new ArrayList<>();
// Getters and setters.
}
这是我的 DML
insert into products (product_id, upc, sku, description, price) values ('1', '1257833283', '9394550220002', 'Diva Jeans', 39.99);
insert into products (product_id, upc, sku, description, price) values ('2', '1358743283', '7394650110003', 'Polo Shirt', 19.99);
insert into products (product_id, upc, sku, description, price) values ('3', '1458843283', '7394750120000', 'Floral Swing Skirt', 69.99);
insert into products (product_id, upc, sku, description, price) values ('4', '1358753283', '7394850130001', 'Denim Short', 29.99);
insert into products (product_id, upc, sku, description, price) values ('5', '1258793283', '7394950140000', 'True Skinny Jeans', 49.99);
insert into orders (order_id, order_number, tax_percent, status) values ('1', 'RTL_1001', 10, 'SHIPPED');
insert into orders (order_id, order_number, discount, tax_percent, status) values ('2', 'RTL_1002', 15.55, 10, 'FULFILLED');
insert into order_product (order_id, product_id) values ('1', '1');
insert into order_product (order_id, product_id) values ('1', '2');
insert into order_product (order_id, product_id) values ('2', '2');
我只想选择那些产品
如果我按不存在的订单查询产品(比如 order_id = 3 不存在),我想返回所有符合条件的产品,因为订单尚未创建。
如果我按确实存在的订单查询产品,那么我希望数据库返回与订单无关的所有产品。例如
order_id = 1
,我希望退回 id = 3、4 和 5 的产品。由于 order_id = 1 已与 product_id = 1 和 2 相关联,因此我不希望退回这些产品。
如果我要编写 JDBC SQL 查询
SELECT p.product_id
FROM Product p
WHERE NOT EXISTS
(
SELECT 1
FROM order_product
WHERE product_id = p.product_id
AND
order_id = ?
)
OR
NOT EXISTS
(
SELECT 1
FROM order_product
WHERE order_id = ?
)
我不知道如何使用 JPA 创建类似的查询。我能想到的都是这样的。
创建一个继承自 JPARepository 的 ProductRepository
从产品表中获取所有产品,包括 order_product 表中的产品。
使用 JPA 获取给定订单 id 的产品,并从 (2) 中的产品中删除所述产品
我希望有更好的方法来做到这一点。
解决方案
Order order = em.getReference(Order.class, orderId);
em.createQuery("select distinct p from Product p where :order not member of p.orders")...;
推荐阅读
- apache - Codeigniter 删除 index.php 在本地工作,但不适用于 aws ELB
- sparql - 如何使用 Python 确定两个 SPARQL 查询是否相同?
- c# - C# WPF Behavior 类,由于 Windows 缩放更改,卸载 UIElement 后 AssociatedObject 为 null
- python - 仅当所有任务完成后才保存任务结果
- swi-prolog - SWI Prolog 字体大小设置
- ios - iOS - 创建大量 UIImageViews 而不会冻结 UI
- javascript - 如何使用 JS 或 JQuery 迭代获取 gridview 单元格值
- python - 轮廓图和 PCA 图具有相同的颜色
- java - 在 Java 中反序列化包含 __type 而不是 @class 的 JSON
- c# - 如果整数看起来像这样 `010` 是第一个 0 考虑整数?