Reputation: 3073
I'm using Native Query, but Hibernate/JPA doesn't work, it always throws
javax.ejb.EJBTransactionRolledbackException: Parameter with that position 1 did not exist
Original SQL Script: (it works fine in SQL Editor)
SELECT CAST(filteredValue.measured_at AS DATE) AS DATE,date_part('hour', filteredValue.measured_at) AS HOUR, filteredValue.source_id, AVG( filteredValue.value ) AS avg_concentration, filteredValue.code
FROM ( SELECT * FROM pollutant_value
WHERE measured_at >= '2017-06-27 11:00:00' AND measured_at <= '2017-06-28 11:00:00'
) filteredValue
GROUP BY filteredValue.source_id, filteredValue.code, CAST(filteredValue.measured_at AS DATE),date_part('hour', filteredValue.measured_at)
ORDER BY CAST(filteredValue.measured_at AS DATE) DESC, date_part('hour', filteredValue.measured_at) DESC, filteredValue.source_id ASC, filteredValue.code ASC
Java Entity Class
@Entity
@Table(name = "pollutant_value")
@NamedQueries({
@NamedQuery(name = PollutantValueEntity.FIND_ALL_BY_SOURCE_ID, query = "SELECT p FROM PollutantValueEntity p WHERE p.sourceId = :sourceId"),
@NamedQuery(name = PollutantValueEntity.COUNT_BY_CODE, query = "SELECT COUNT(p.id) FROM PollutantValueEntity p WHERE p.code = :code"),
@NamedQuery(name = PollutantValueEntity.FIND_ALL, query = "SELECT p FROM PollutantValueEntity p")})
@NamedNativeQueries({
@NamedNativeQuery(name = PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY, query = "SELECT CAST(filteredValue.measured_at AS date) AS date, date_part('hour', filteredValue.measured_at) AS hour, filteredValue.source_id, AVG(filteredValue.value) AS avg_concentration, filteredValue.code "
+ "FROM (SELECT * FROM pollutant_value" + "WHERE measured_at >= ?1 AND measured_at <= ?2) filteredValue"
+ "GROUP BY filteredValue.source_id, filteredValue.code, CAST (filteredValue.measured_at AS date), date_part('hour', filteredValue.measured_at)"
+ "ORDER BY CAST(filteredValue.measured_at AS date) DESC, date_part('hour', filteredValue.measured_at) DESC, filteredValue.source_id ASC, filteredValue.code ASC ", resultSetMapping = PollutantValueEntity.AVG_POLLUTANT_VALUE_RESULT_MAPPER) })
@SqlResultSetMapping(name = PollutantValueEntity.AVG_POLLUTANT_VALUE_RESULT_MAPPER, classes = {
@ConstructorResult(targetClass = AvgGroupedPollutantValueByHourEntity.class, columns = {
@ColumnResult(name = "date"), @ColumnResult(name = "hour"), @ColumnResult(name = "source_id"),
@ColumnResult(name = "avgConcentration"), @ColumnResult(name = "code") }) })
public class PollutantValueEntity extends GenericEntity implements Serializable {
private static final String PREFIX = "com.axonactive.iot.sniffer.entity.PollutantValueEntity";
public static final String FIND_ALL_BY_SOURCE_ID = PREFIX + ".findBySniffer";
public static final String FIND_ALL = PREFIX + ".findAll";
public static final String COUNT_BY_CODE = PREFIX + ".countByCode";
public static final String FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY = PREFIX + ".findAvgConcentrationByHourInDay";
public static final String AVG_POLLUTANT_VALUE_RESULT_MAPPER = PREFIX + ".averagePollutantResult";
And the service call
public List<AvgGroupedPollutantValueByHourEntity> getAvgPollutantValuesByLowerBoundAndUpperBound( Date lowerBound, Date upperBound){
Query query = getEm().createNativeQuery(PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY, PollutantValueEntity.AVG_POLLUTANT_VALUE_RESULT_MAPPER);
query.setParameter(1, "2017-06-27 11:00:00");
query.setParameter(2, "2017-06-28 11:00:00");
return query.getResultList();
}
I don't know why the NamedNativeQuery PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY
doesn't take the parameters as intended.
Did I miss something ?
Edit #1:
Because createNativeQuery
method of EntityManager take in a SQL Query string, but in the entity class, I declared it with a name.
So how can I still keep the name of this named native query with the annotation
@NamedNativeQuery
and create it from EntityManager em
, since em
doesn't have the method like createNamedNativeQuery
Upvotes: 0
Views: 1585
Reputation: 11531
Your problem is that you defined a NAMED query, and then invoked it like this
Query query = em.createNativeQuery(PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY, PollutantValueEntity.AVG_POLLUTANT_VALUE_RESULT_MAPPER);
query.setParameter(1, "2017-06-27 11:00:00");
query.setParameter(2, "2017-06-28 11:00:00");
return query.getResultList();
which is basically creating a query with SQL for whatever String is "PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY"
i.e "com.axonactive.iot.sniffer.entity.PollutantValueEntity.findAvgConcentrationByHourInDay" which is not SQL clearly. If using that method you pass the SQL in directly to the createNativeQuery
method.
A NAMED query should be instantiated like this
query = em.createNamedQuery(PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY);
query.setParameter(1, "2017-06-27 11:00:00");
query.setParameter(2, "2017-06-28 11:00:00");
return query.getResultList();
and then you should be able to set your parameters on it, since that has the actual SQL to be invoked
Upvotes: 2
Reputation: 734
Don't use a number after the ?. Write ?, not ?1.
@NamedNativeQuery(name = PollutantValueEntity.FIND_AVG_CONCENTRATION_BY_HOUR_IN_DAY, query = "SELECT CAST(filteredValue.measured_at AS date) AS date, date_part('hour', filteredValue.measured_at) AS hour, filteredValue.source_id, AVG(filteredValue.value) AS avg_concentration, filteredValue.code "
+ "FROM (SELECT * FROM pollutant_value" + "WHERE measured_at >= ? AND measured_at <= ?) filteredValue"
+ "GROUP BY filteredValue.source_id, filteredValue.code, CAST (filteredValue.measured_at AS date), date_part('hour', filteredValue.measured_at)"
+ "ORDER
Checkout the the Hibernate Documentation: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html
16.1.7. Parameters
Native SQL queries support positional as well as named parameters:
Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
List pusList = query.setString(0, "Pus%").list();
Upvotes: 0