【问题标题】:javax.persistence.Query does not set parameterjavax.persistence.Query 未设置参数
【发布时间】:2016-11-19 07:07:22
【问题描述】:

这是我正在执行的查询实例

entityManager.createNativeQuery(SHIPMENTS_UNION_QUERY, RESULT_MAPPER)
                .setParameter("aggreagateCategories", aggregatePCNames)
                .setParameter("startDate", startDate)
                .setParameter("endDate", endDate)
                .setParameter("individualCategories", individualPCNames)
                .getResultList();

上面一行的执行日志是

12:29:36.909 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [3]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [6]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 'AirConditioner' -> aggreagateCategories [1]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [2]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [5]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 'Cooler', 'Heater', 'Dryer' -> individualCategories [4]

当使用硬编码到查询本身的参数执行上述查询时,查询执行得很好,结果被提取并映射到与@SqlResultSetMapping 对应的RESULT_MAPPER,但是当使用上述setParameter 语句执行此操作时,执行不会返回任何结果..

请帮助确定问题。

EDIT1

硬编码查询

SELECT ac.category_name category_name, SUM(ais.volume) volume,   qc.date, qc.quarter as quarter, qc.year 
FROM actual_industry_shipment ais 
JOIN quarter_calendar qc ON ais.quarter=qc.id  
JOIN product_category pc ON ais.product_category_id=pc.id 
JOIN aggregated_product_categories ac ON ac.id = pc.aggregate_category_id 
WHERE ac.category_name IN ('AirConditioner') 
AND qc.date BETWEEN  '2010-01-01' AND '2011-01-01' 
GROUP BY pc.aggregate_category_id, qc.quarter, qc.year 
UNION 
SELECT pc.category_name category_name, ais.volume volume,   qc.date, qc.quarter as quart, qc.year 
FROM actual_industry_shipment ais  
JOIN quarter_calendar qc ON ais.quarter=qc.id  
JOIN product_category pc ON ais.product_category_id=pc.id 
WHERE pc.category_name IN ('Dryer', 'Cooler') 
AND qc.date BETWEEN  '2010-01-01' AND '2011-01-01'

使用参数查询

SELECT ac.category_name category_name, SUM(ais.volume) volume,   qc.date, qc.quarter as quarter, qc.year 
FROM actual_industry_shipment ais 
JOIN quarter_calendar qc ON ais.quarter=qc.id
JOIN product_category pc ON ais.product_category_id=pc.id
JOIN aggregated_product_categories ac ON ac.id = pc.aggregate_category_id 
WHERE ac.category_name IN (?) 
AND qc.date BETWEEN  ? AND ? 
GROUP BY pc.aggregate_category_id, qc.quarter, qc.year
UNION 
SELECT pc.category_name category_name, ais.volume volume,   qc.date, qc.quarter as quart, qc.year 
FROM actual_industry_shipment ais  
JOIN quarter_calendar qc ON ais.quarter=qc.id  
JOIN product_category pc ON ais.product_category_id=pc.id 
WHERE pc.category_name IN (?) 
AND qc.date BETWEEN  ? AND ?

在代码中声明的原生查询

private static final String SHIPMENTS_UNION_QUERY =
        "SELECT ac.category_name category_name, SUM(ais.volume) volume,   qc.date, qc.quarter as quarter, qc.year " +
                "FROM actual_industry_shipment ais " +
                "JOIN quarter_calendar qc " +
                "ON ais.quarter=qc.id  " +
                "JOIN product_category pc " +
                "ON ais.product_category_id=pc.id " +
                "JOIN aggregated_product_categories ac " +
                "ON ac.id = pc.aggregate_category_id " +
                "WHERE " +
                "ac.category_name IN (:aggreagateCategories) " +
                "AND qc.date BETWEEN  :startDate AND :endDate " +
                "GROUP BY " +
                "pc.aggregate_category_id, qc.quarter, qc.year " +

                "UNION " +

                "SELECT pc.category_name category_name, ais.volume volume,   qc.date, qc.quarter as quart, qc.year " +
                "FROM actual_industry_shipment ais  " +
                "JOIN quarter_calendar qc " +
                "ON ais.quarter=qc.id  " +
                "JOIN product_category pc " +
                "ON ais.product_category_id=pc.id " +
                "WHERE pc.category_name IN (:individualCategories) " +
                "AND qc.date BETWEEN  :startDate AND :endDate";

【问题讨论】:

  • 您能否添加导致问题的 SHIPMENTS_UNION_QUERY 的代码?
  • 请发布您尝试执行的查询。
  • 发现问题了,我一直将参数作为引用文本而不是setParameter中的List发送到IN子句,但仅在Hibernate中支持

标签: java hibernate spring-data-jpa jpa-2.0 jpa-2.1


【解决方案1】:

命名参数查询与原始硬编码 Native SQL 查询不完全相同,您可以查看以下内容(仅获取查询的不同部分):

参数查询:

category_name, ais.volume volume,   qc.date, 
qc.quarter as quart, qc.year FROM 
actual_industry_shipment ais  
JOIN quarter_calendar qc ON

硬编码查询:

ais.quarter=qc.id  JOIN category_name, 
ais.volume volume,  product_category pc ON ais.product_category_id=pc.id WHERE 
pc.category_name IN ('Dryer', 'Cooler') AND qc.date 
BETWEEN  '2010-01-01' AND '2011-01-01'

【讨论】:

  • 我正在使用命名参数,添加一个更新
  • JPA 不需要实现来支持本机查询中的命名参数,但 Hibernate 将其作为附加功能。如果 OP 切换到 EclipseLink 它将无法工作,但这不是问题。
  • @coladict 也尝试使用位置参数,也没有用
  • Hibernate 生成的查询(带参数)与原始的 Native SQL 查询不完全相同,你确定你在两者中使用相同的查询吗?
  • @javaguy 我看到命名参数转换为?对于prepared statement,你发现还有什么不同的地方
【解决方案2】:

您的日期参数未绑定为字符串,因为您的硬编码查询似乎是并且正在工作,同样的日期应用于与硬编码查询不同的开始日期和结束日期。

12:29:36.909 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [3]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [6]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 'AirConditioner' -> aggreagateCategories [1]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [2]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [5]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 'Cooler', 'Heater', 'Dryer' -> individualCategories [4]

您的有效查询在引号中包含日期,

BETWEEN  '2010-01-01' AND '2011-01-01'

【讨论】:

  • 你几乎拥有它。他将相同的日期绑定到 startDate 和 endDate。我的同事做了同样的事情,没有意识到他必须使用新的 java.util.Date 对象来设置两个参数,而不是重用它并调用 setYear 或任何正在使用的 OP。他所做的是Date endDate = startDate; endDate.setMonth(...); 然后绑定它。我认为我的 OP 一定也做了同样的事情,没有意识到 endDate 和 startDate 是同一个对象,而不是彼此的副本。
【解决方案3】:

这是我们看到问题的地方:

12:29:36.909 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [3]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> endDate [6]
12:29:36.910 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 'AirConditioner' -> aggreagateCategories [1]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [2]
12:29:36.912 DEBUG org.hibernate.loader.Loader : bindNamedParameters() 2010-01-01 -> startDate [5]

您对两者的绑定日期相同。 我猜你的代码看起来像:

Date endDate = getDateParameter(...);
Date startDate = endDate;
startDate.setYear(endDate.getYear()-1);

问题在于startDateendDate 不是彼此的副本,而是完全相同的对象。当您更改 startDate 上的日期时,您已经更改了 endDate。 你应该像这样复制它:

Date startDate = new Date(endDate.getTime());

【讨论】:

  • 我不认为这是问题所在,日期作为我给出的字符串可以正常工作,即使在同一日期之间也是如此。
猜你喜欢
  • 1970-01-01
  • 2014-02-15
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2017-04-08
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多