java - 用于在单个表中查找最新的半唯一行的 Hibernate 实体查询

标签 java sql hibernate

我有一个带有单个表的 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 最新购买的笔记本或铅笔。”

并会提供:

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) 以仅获取那些列,而我需要使用以下格式:

从 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-fu 不是我的强项。

编辑:

请注意,我目前正在使用 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:

因为,如上所述,添加一个 projection/distinct column set 似乎向 Hibernate 表明我想要 those columns 作为结果/返回值,而我想要的只是简单地限制返回值基于唯一列值的模型对象

最佳答案

首先,使用聚合查询获取产品 + 购买者组合的最后购买日期。

将该查询用作匹配元组的子选择:

from Puchases p 
where (p.PRODUCT_NAME, p1.PURCHASER_NAME, p1.PURCHASE_DATE) in
    (select PRODUCT_NAME, PURCHASER_NAME , max(PURCHASE_DATE) 
     from Purchases 
     where 
        PRODUCT_NAME in :productNames and 
        PURCHASER_NAME in :purchaserNames 
     group by PRODUCT_NAME, PURCHASER_NAME)

使用标准 API 也应该可以使用 Subqueries.propertiesIn 实现相同的功能。

参见 Hibernate Criteria Query for multiple columns with IN clause and a subselect

如果您的 PURCHASE_ID 保证“按时间顺序递增”,那么您可以简单地在子选择中使用 max(PURCHASE_ID)。

关于java - 用于在单个表中查找最新的半唯一行的 Hibernate 实体查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52302676/

相关文章:

java - 为什么在java中与pip行的字符串连接不返回任何内容(空字符串)?

sql - 在 SQL Server 2008 R2 中使用 PIVOT 表

Hibernate:与同一类的多个关联

java - 找不到部署 "war"的子部署 "ear"中命名的持久性单元

java - 计算二进制数中 1 的最佳方法

java - 二维平面上的重叠多边形

即使加载数据,JavaFx Tableview 数据库也不可见

mysql - 在(Mysql?)中存储不重叠日期范围的最佳方法是什么?

sql - 三向左连接中的 ORDER BY 与 DISTINCT

Java Hibernate使用case when else查询导致hql中的异常