如何以编程方式编写内部查询以根据条件获取最新记录

问题描述 投票:0回答:1

我的用例是根据一些过滤条件从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和isVaribaleWe​​ight将在运行时以编程方式传递。上面以示例为目的。

这是我的实体模型的样子(其他不需要的列已删除:-

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.create_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);

我开始收到奇怪的错误提示,原因是:com.microsoft.sqlserver.jdbc.SQLServerException:无效的列名'create_ts'。

这里是相同的完整堆栈跟踪:-

Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:80)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2123)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1911)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
at org.hibernate.loader.Loader.doQuery(Loader.java:932)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
at org.hibernate.loader.Loader.doList(Loader.java:2615)
at org.hibernate.loader.Loader.doList(Loader.java:2598)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
at org.hibernate.loader.Loader.list(Loader.java:2425)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153)
at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:991)
at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:147)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
at org.hibernate.query.Query.getResultList(Query.java:146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:380)
at com.sun.proxy.$Proxy182.getResultList(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
... 65 common frames omitted

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name 'create_ts'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:256)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1621)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:592)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:522)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2930)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:248)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:223)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:444)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:71)

我检查了2-3次,并确认表中存在列名“ create_ts”列。

作为查询的一部分,我也需要分页支持,即,如果用户输入pageNum = 1且pagesize = 10,则如果记录更多,我应该能够返回10个结果。当用户输入pageNum = 2,pageSize = 10时,我应该返回下10条记录。

有人可以研究它,并指导我如何使用Spring Data Jpa / Criteria实现这一目标吗?

sql-server jpa spring-data-jpa criteria
1个回答
0
投票

您正在寻找的是“每组前N个项目”的解决方案。在您喜欢的搜索引擎中使用此短语,将出现解决问题的几种方法。我选择的是

  • 窗口功能
  • [CROSS APPLY加入子查询。
© www.soinside.com 2019 - 2024. All rights reserved.