【发布时间】:2018-01-27 08:25:40
【问题描述】:
我在本机查询 (SQL Server) 上使用分页,该查询适用于初始页面请求第 0 页,但当我尝试获取第 2 页的结果时因列名无效而失败。生成的查询在 SSMS 中有效,但在 Spring 中无效。
感谢任何见解。
这是错误:
Hibernate:
/* dynamic native SQL query */ WITH query AS (SELECT
inner_query.*,
ROW_NUMBER() OVER (
ORDER BY
CURRENT_TIMESTAMP) as __hibernate_row_nr__
FROM
( SELECT
TOP(?) p.ProductKey as page0_,
p.ProductName as page1_,
p.Sku as page2_,
p.MaterialKey as page3_,
p.MfgItemNumber as page4_,
p.PackageSize as page5_,
p.PriceUom as page6_,
p.CasePack as page7_,
p.ProductDescription as page8_,
P.MediaDomain as page9_,
p.ImagePath as page10_,
p.ImageName as page11_,
plp.Price as page12_,
plp.ListPrice as page13_,
p.SearchText as page14_
FROM
[dbo].[BdmProductCategory] pc
INNER JOIN
[dbo].BdmProduct p
on pc.ProductKey = p.productKey
INNER JOIN
[dbo].BdmPriceListProduct plp
on plp.ProductKey = p.ProductKey
WHERE
pc.CategoryKey = ?
AND pc.ProductKey > 0
AND pc."Delete" = 0
AND plp.PriceListKey = ? -- #pageable
order by
sku asc ) inner_query ) SELECT
page0_,
page1_,
page2_,
page3_,
page4_,
page5_,
page6_,
page7_,
page8_,
page9_,
page10_,
page11_,
page12_,
page13_,
page14_
FROM
query
WHERE
__hibernate_row_nr__ >= ?
AND __hibernate_row_nr__ < ?
2017-08-18 08:47:45.844 TRACE 19316 --- [nio-6193-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [4143]
2017-08-18 08:47:45.845 TRACE 19316 --- [nio-6193-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [657]
2017-08-18 08:47:45.980 WARN 19316 --- [nio-6193-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: S1093
2017-08-18 08:47:45.980 ERROR 19316 --- [nio-6193-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : The column name productKey is not valid.
2017-08-18 08:47:45.990 ERROR 19316 --- [nio-6193-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not execute query; nested exception is org.hibernate.exception.GenericJDBCException: could not execute query] with root cause com.microsoft.sqlserver.jdbc.SQLServerException: The column name productKey is not valid.
这是模型:
@Entity
@Table(name = "vw_BdmProductInfo") // A view!
public class BdmProductInfo {
@Id
private Long productKey;
private Long materialKey;
private String sku;
private BigDecimal price;
private BigDecimal listPrice;
private String priceUom;
private String casePack;
private String packageSize;
private String mfgItemNumber;
private String productName;
private String productDescription;
private String mediaDomain;
private String ImagePath;
private String imageName;
private String searchText;
protected BdmProductInfo() {}
....
这里是存储库:
@RestResource(path="findProductInfoByCategory")
@Query(value="SELECT p.ProductKey, p.ProductName, p.Sku, p.MaterialKey, p.MfgItemNumber, p.PackageSize, p.PriceUom, p.CasePack, p.ProductDescription, P.MediaDomain, p.ImagePath, p.ImageName, plp.Price, plp.ListPrice, p.SearchText "
+ "FROM [dbo].[BdmProductCategory] pc "
+ "INNER JOIN [dbo].BdmProduct p on pc.ProductKey = p.productKey "
+ "INNER JOIN [dbo].BdmPriceListProduct plp on plp.ProductKey = p.ProductKey "
+ "WHERE pc.CategoryKey = :categoryKey "
+ "AND pc.ProductKey > 0 "
+ "AND pc.\"Delete\" = 0 "
+ "AND plp.PriceListKey = :priceListKey \n-- #pageable\n ",
countQuery="SELECT Count(*) "
+ "FROM [dbo].[BdmProductCategory] pc "
+ "INNER JOIN [dbo].BdmProduct p on pc.ProductKey = p.productKey "
+ "INNER JOIN [dbo].BdmPriceListProduct plp on plp.ProductKey = p.ProductKey "
+ "WHERE pc.categoryKey = :categoryKey "
+ "AND pc.ProductKey > 0 "
+ "AND pc.\"Delete\" = 0 "
+ "AND plp.PriceListKey = :priceListKey ",nativeQuery=true)
Page<BdmProductInfo> findProductInfoByCategory(@Param("categoryKey") Long categoryKey, @Param("priceListKey") Long priceListKey, Pageable pageable );
【问题讨论】:
-
productKey 列好像不存在?!您能否在此处检查日志:无法执行查询] 根本原因 com.microsoft.sqlserver.jdbc.SQLServerException:列名 productKey 无效。你确定第一次调用成功了吗?!
-
是的,第一次调用成功......但查询与第二次请求不同。第一个查询Hibernate使用了Top函数,第二个使用了WITH QUERY、row_nbr等......如下图..
-
WITH 查询 AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as hibernate_row_nr FROM (SELECT TOP(?) p.ProductKey as page0_, p. ProductName 作为 page1_,p.Sku 作为 page2_,p.MaterialKey 作为 page3_,p.MfgItemNumber 作为 page4_,p.PackageSize 作为 page5_,p.PriceUom 作为 page6_,p.CasePack 作为 page7_,p.ProductDescription 作为 page8_,P.MediaDomain 作为page9_, p.ImagePath as page10_,
-
p.ImageName as page11_, plp.Price as page12_, plp.ListPrice as page13_, p.SearchText as page14_ FROM [dbo].[BdmProductCategory] pc INNER JOIN [dbo].BdmProduct p on pc .ProductKey = p.productKey INNER JOIN [dbo].BdmPriceListProduct plp on plp.ProductKey = p.ProductKey WHERE pc.CategoryKey = ? AND pc.ProductKey > 0 AND pc."Delete" = 0 AND plp.PriceListKey = ? -- #pageable
-
这就是问题所在......在为查询列创建别名后,Hibernate 使用别名而不是尝试生成自己的别名......导致问题。因此,在查询中,为每一列选择 p.productKey 作为 productKey 等的别名,这有助于获取后续页面 ... FWIW 为遇到此问题的其他人提供...
标签: sql spring pagination spring-data spring-data-jpa