我有一个Hibernate数据库,其中只有一张表,看起来像这样:
PURCHASE_ID | PRODUCT_NAME | PURCHASE_DATE | PURCHASER_NAME | PRODUCT_CATEGORY
------------------------------------------------------------------------------
1 Notebook 09-07-2018 Bob Supplies
2 Notebook 09-06-2018 Bob Supplies
3 Pencil 09-06-2018 Bob Supplies
4 Tape 09-10-2018 Bob Supplies
5 Pencil 09-09-2018 Steve Supplies
6 Pencil 09-06-2018 Steve Supplies
7 Pencil 09-08-2018 Allen Supplies
我希望仅基于一些其他的限制条件返回最新的购买记录。例如:
List<Purchase> getNewestPurchasesFor(Array<String> productNames, Array<String> purchaserNames) { ... }
可以使用以下方式进行调用:
List<Purchase> purchases = getNewestPurchasesFor(["Notebook", "Pencil"], ["Bob", "Steve"]);
用英语表达,“给我Bob或Steve买的最新款Notebook或Pencil的购买记录。”
将提供:
PURCHASE_ID | PRODUCT_NAME | PURCHASE_DATE | PURCHASER_NAME
-----------------------------------------------------------
1 Notebook 09-07-2018 Bob
3 Pencil 09-06-2018 Bob
5 Pencil 09-09-2018 Steve
所以它就像在多个列上进行“不同”的查找,或者基于某些后排序的组合列唯一键来进行“限制”,但我发现的所有示例都显示使用 SELECT DISTINCT (PRODUCT_NAME, PURCHASER_NAME)
仅获取这些列,而我需要使用以下格式:
from Purchases as entity where ...
这样模型类型就会返回,并保持关系完整。
目前,我的查询还会将所有旧购买记录返回:
PURCHASE_ID | PRODUCT_NAME | PURCHASE_DATE | PURCHASER_NAME | PRODUCT_CATEGORY
------------------------------------------------------------------------------
1 Notebook 09-07-2018 Bob Supplies
2 Notebook 09-06-2018 Bob Supplies
3 Pencil 09-06-2018 Bob Supplies
5 Pencil 09-09-2018 Steve Supplies
6 Pencil 09-06-2018 Steve Supplies
对于重复购买,这会导致性能大幅下降。
我应该使用哪些特殊关键字来实现这一点?查询语言和SQL技巧并不是我的强项。
编辑:
请注意,我目前正在使用Criteria
API,并希望继续使用它。
Criteria criteria = session.createCriteria(Purchase.class);
criteria.addOrder(Order.desc("purchaseDate"));
// Product names
Criterion purchaseNameCriterion = Restrictions.or(productNames.stream().map(name -> Restrictions.eq("productName", name)).toArray(Criterion[]::new));
// Purchaser
Criterion purchaserCriterion = Restrictions.or(purchaserNames.stream().map(name -> Restrictions.eq("purchaser", name)).toArray(Criterion[]::new));
// Bundle the two together
criteria.add(Restrictions.and(purchaseNameCriterion, purchaserCriterion));
criteria.list(); // Gives the above results
如果我尝试使用不同的投影方式,就会出现错误:
ProjectionList projections = Projections.projectionList();
projections.add(Projections.property("productName"));
projections.add(Projections.property("purchaser"));
criteria.setProjection(Projections.distinct(projections));
结果为:
17:08:39 ERROR Order by expression "THIS_.PURCHASE_DATE" must be in the result list in this case; SQL statement:
因为如上所述,添加一个投影/不同的列集似乎会告诉Hibernate我希望将这些列作为结果/返回值,而我想要的是仅基于唯一列值限制返回的模型对象。
Bob/Pencil
的第8行,那么它将被返回,而不是ID为3的条目。(准确地回答查询:“给我Bob或Steve购买的最新笔记本电脑或铅笔。”) - Craig Otis4 Pencil 09-09-2018 Steve
,但实际数据是4 Tape 09-10-2018 Bob Supplies
,你能用正确的示例进行修正吗?谢谢。 - Leviand