【发布时间】:2020-06-01 13:16:46
【问题描述】:
我的用例是根据 SQL 表中的一些过滤条件查找最新记录(按日期)。我已经构建了 SQL 查询并通过 SQL IDE 运行它,它工作正常。我正在使用 MS Sql Serve 作为我的数据库。
但是当我尝试使用 Spring-Data JPA/Criteria 以编程方式转换此查询时,我不知道如何实现。
这是我根据 src_cc、src_nbr 和 isvariableWeight 查找最新记录的查询:-
SELECT *
FROM
dcfin_test Tab1
INNER JOIN (
SELECT
ibd_doc_nbr,
ibd_doc_line_nbr,
MAX(create_ts) AS max_Ts
FROM
dcfin_test
WHERE
src_cc = 'US'
AND src_nbr = 6938
AND isvariableWeight = 'Y'
GROUP BY
ibd_doc_nbr,
ibd_doc_line_nbr) Tab2 ON Tab1.ibd_doc_nbr = Tab2.ibd_doc_nbr
AND Tab1.ibd_doc_line_nbr = Tab2.ibd_doc_line_nbr
AND Tab1.create_ts = Tab2.max_Ts;
这里 src_cc、src_nbr 和 isVaribaleWeight 将在运行时以编程方式传递。上面显示的目的是为了举例。
这是我的实体模型的样子(其他不需要的列已被删除):-
import java.math.BigDecimal;
import java.time.Instant;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@Table(name = "dcfin_test")
@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WeightedAlertEntity {
@Id
@Column(name = "weightedAlertId")
private String weightedAlertId;
@Column(name = "src_cc")
private String sourceCC;
@Column(name = "src_nbr")
private int sourceNbr;
@Column(name = "isVaribaleWeight")
private String isVaribaleWeight;
@Column(name = "ibd_doc_nbr")
private String inboundDocNbr;
@Column(name = "ibd_doc_line_nbr")
private String inboundDocNbrLineNbr;
@Column(name = "item_nbr")
private String itemNbr;
@Column(name = "wac_percent_change")
private BigDecimal percentWacChange;
@Column(name = "waw_percent_change")
private BigDecimal percentWawChange;
@Column(name = "created_by")
private String createdBy;
@Column(name = "create_ts")
private Instant createTs;
}
我尝试在 Spring Data JPA 中使用本机查询,它看起来如下:-
@Repository
public interface WeightedAlertEntityDao
extends JpaRepository<WeightedAlertEntity, String> {
@Query(value = "SELECT * FROM dcfin_weighted_alert_data Tab1 "
+ "INNER JOIN ("
+ "SELECT ibd_doc_nbr,ibd_doc_line_nbr,MAX(create_ts) AS max_Ts FROM dcfin_weighted_alert_data"
+ " WHERE src_cc = ?1 AND src_nbr = ?2 AND weight_format_type = ?3 "
+ "GROUP BY ibd_doc_nbr, ibd_doc_line_nbr) Tab2 "
+ "ON Tab1.ibd_doc_nbr = Tab2.ibd_doc_nbr "
+ "AND Tab1.ibd_doc_line_nbr = Tab2.ibd_doc_line_nbr "
+ "AND Tab1.create_ts = Tab2.max_Ts", nativeQuery = true)
public List<WeightedAlertEntity> getAlertEntityBasedOnFilterCondition(
String sourceCC, Integer srcNbr, String weightFormatType);
}
当我从我的服务层调用上述方法时:-
List<WeightedAlertEntity> alertEntityBasedOnFilterCondition = weightedAlertDao.getAlertEntityBasedOnFilterCondition(
header.getFacilityCountryCode(),Integer.parseInt(header.getFacilityNum()),
weightFormatType);
更新我的问题:-
我已经彻底检查过,发现有一个错误导致列名无效,因为我使用 Tab2.create_ts 代替了 Tab2.max_Ts。现在我可以得到结果了。
作为此查询的一部分,我也需要分页支持,即如果用户输入 pageNum = 1 和 pagesize = 10,如果记录更多,我应该能够返回 10 个结果。 当用户输入 pageNum = 2, pageSize = 10 时,我应该返回接下来的 10 条记录。
有人可以调查一下并指导我如何使用 Spring Data Jpa / Criteria 实现这一目标吗?
【问题讨论】:
-
如果您只想要
modified_ts的MAX值,为什么不在外部查询中使用窗口化的MAX?这里不需要子查询。 -
我正在寻找完整的行数据(它将是记录列表),而不仅仅是 modfied_ts。 Modified_ts 是用于查找最新记录的列。
-
有一个复杂的查询,但您还没有展示如何在 JPA 中映射任何内容。你的模型是什么样的,你尝试了什么,你希望在你的应用程序中使用什么结果?分页是在您计算完其他所有内容之后进行的 - 否则,只需使用本机 SQL 查询并获取原始数据。
-
@Chris 我已经根据我迄今为止的尝试编辑了这个问题。
标签: sql-server jpa spring-data-jpa criteria