JPQL Average Time Difference - jpa

I have order bills and good receive bills. Any bill can have multiple bill items. One order bill item may have none or more receive bill items.
I want to calculate the lead time, which is the average time difference between the order and the good receipt in a JPQL (Java Persistance Query Language) query in days. I use EclipseLink 2.4 as the persistence provider.
This is the query I attempted. Is there any way I can take the average lead time using JPQL ?
jpql = "Select avg(b.createdAt - rb.createdAt) "
+ " from BillItem bi "
+ " join bi.bill b "
+ " joib bi.referanceBillItem rbi "
+ " join rbi.bill rb "
+ " where b.billType in :bts "
+ " and rb.billType in :rbts "
+ " and bi.item=:amp "
+ " and b.createdAt between :fd and :td "
+ " ";

Related

JpaSystemException: No Dialect mapping for JDBC type: 1111

I have viewed some of the related question but the solutions on them are bit older. Most of them are using EntityManager. I have written the following native query in JpaRepository and when I get geojson as a String I'm getting the error mentioned in the title.
Here is my query
#Query(value = "SELECT\n"
+ " json_build_object(\n"
+ " 'type', 'FeatureCollection',\n"
+ " 'features', json_agg(\n"
+ " json_build_object(\n"
+ " 'type', 'Feature',\n"
+ " 'geometry', ST_AsGeoJSON(a.check_in_geom)\\:\\:json,\n"
+ " 'properties', json_build_object(\n"
+ " 'username', a.username,\n"
+ " 'users', (\n"
+ " -- Generate json array of \"users\"\n"
+ " SELECT array_to_json(array_agg(u.*)) \n"
+ " FROM users u \n"
+ " WHERE u.username = a.username\n"
+ " GROUP BY u.username\n"
+ " )\n"
+ " )\n"
+ " )\n"
+ " )\n"
+ " ) Json\n"
+ "FROM\n"
+ " attendances a, users u\n"
+ " WHERE a.username = u.username AND u.designation = 'Manager' AND date_trunc('day', a.created_at)\\:\\:DATE = '2022-04-04'"
+ " ;", nativeQuery = true)
String getAttendanceGeoJsonByDesignationAndDate(String designation, String dateStr);
For now I'm passing designation and date as static values.
When I run this query on Postgresql it runs successfully and return the expected geojson. But spring boot does not allow the result to be as String or it throws exception while running the query.
Please let me know how can I fix it. Also if I need to provide more detail, do let me know.

unexpected token: :(colon) in Hibernate

I'm trying to do the following code, but i get the unexpected token: : near line 1 error which refer to ord.date_out::date. Here is my code
#Query(value="select new com.ameerarestapi.wrapper.report.SummaryPeriodicSales(sto.name, sum(odi.subtotal_price), sum(odi.qty), ((sum(odi.subtotal_price))/(sum(odi.qty))), ord.date_out::date) "
+ "from OrderDetailItem odi "
+ "left join odi.order as ord "
+ "left join ord.store as sto "
+ "where ord.store.principle = :principle and ord.orderStatus IN :orderstatus and ord.dateOut between :date1 and :date2 and ord.voidStatus = :voidStatus "
+ "group by sto.name, ord.date_out::date ")
List<SummaryPeriodicSales> getReportDaily(#Param("principle") Principle principle,#Param("orderstatus") List<OrderStatus> orderstatus,#Param("date1") Date date1,#Param("date2") Date date2,#Param("voidStatus") byte voidStatus);
I'm using postgre database
Use the standard CAST() operator instead:
CAST(ord.date_out AS date)

Transforming complex postgres query into JPQL for Spring Hibernate repository

I have the following Postgres SQL query, in order to get alerts with the latest date:
SELECT latest_alerts.subject_id,
latest_alerts.alertconfiguration_id_id,
latest_alerts.alert_level,
latest_alerts.maxdate
FROM (SELECT subject_id,
alertconfiguration_id_id,
alert_level,
Max(date) AS maxdate
FROM alert
WHERE subject_id IN ( 'da157532-8de5-4c0c-8608-d924e670d5db', '63b99886-77c8-4784-b8f0-7ff5310f1272' )
AND alertconfiguration_id_id IN (
'6feb6b8b-6b96-4d5d-ac58-713b3cd637a0'
)
GROUP BY subject_id,
alertconfiguration_id_id,
alert_level) AS latest_alerts
INNER JOIN alert
ON alert.date = latest_alerts.maxdate
AND alert.subject_id = latest_alerts.subject_id
AND alert.alertconfiguration_id_id =
latest_alerts.alertconfiguration_id_id
AND alert.alert_level IN ( 'WARNING' )
ORDER BY latest_alerts.maxdate DESC;
This runs well on the postgres database generated by Hibernate. Note the odd id_id construction is because of an embedded key.
But I'm struggling to transform this into a JPA/JPQL query that I can use in a Spring Boot application. So far I have this:
#Query("SELECT" +
" latest_alerts.subject," +
" latest_alerts.alertConfiguration," +
" latest_alerts.alertLevel," +
" latest_alerts.max_date" +
"FROM" +
" (SELECT" +
" subject," +
" alertConfiguration," +
" alertLevel," +
" MAX(date) AS max_date" +
" FROM" +
" alert" +
" WHERE" +
" subject.id IN (:subjectIds) AND alertConfiguration.id.id IN (:alertConfigurationIds)" +
" GROUP BY" +
" subject, alertConfiguration, alertLevel) AS latest_alerts" +
" INNER JOIN" +
" alert" +
" ON" +
" alert.date = latest_alerts.max_date" +
" AND alert.subject = latest_alerts.subject" +
" AND alert.alertConfiguration = latest_alerts.alertConfiguration" +
" AND alert.alertlevel IN (:alertLevels)" +
" ORDER BY latest_alerts.date DESC")
Page<Alert> findLatest(#Param("subjectIds") List<UUID> subjectIds,
#Param("alertConfigurationIds") List<UUID> alertConfigurationIds,
#Param("alertLevels") List<AlertLevel> alertLevels,
Pageable pageable);
But Hibernate doesn't understand what to do with this to the point where it actually throws a nullpointer while parsing this query.
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page ournamespace.sense.repository.AlertRepository.findLatest(java.util.List,java.util.List,java.util.List,org.springframework.data.domain.Pageable)!
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:93)
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:63)
... many more
Caused by: java.lang.NullPointerException
at org.hibernate.hql.internal.antlr.HqlBaseParser.identPrimary(HqlBaseParser.java:4355)
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:993)
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3549)
Any idea if this kind of query is even possible? With a nullpointer thrown by Hibernate it's a bit hard to see what part of the query is the problem.
Cannot do it with Hibernate. From the documentation:
Note that HQL subqueries can occur only in the select or where
clauses.
But you can use native query:
#Query(
value = "SELECT latest_alerts.subject_id,
latest_alerts.alertconfiguration_id_id,
latest_alerts.alert_level,
latest_alerts.maxdate ...
FROM ...",
nativeQuery = true)
Page<Alert> findLatest(#Param("subjectIds") List<UUID> subjectIds,
#Param("alertConfigurationIds") List<UUID> alertConfigurationIds,
#Param("alertLevels") List<AlertLevel> alertLevels,
Pageable pageable);

multiple use of expression via jpql alias keyword

I'm using spring data with a postgresql server and i want to perform some GPS-data range queries. This means, given a coordinate i compute on the fly the distance from the entry to the given point and check for a certain range.
Since i also want to order my data regarding the distance and additionally i want to retrieve the actual distance too, in sql i would use the AS keyword to compute the expression only once and then use this auxiliary expression in the where and the order by part.
However, so far I haven't yet figured out how to do this in jqpl. So my query should do something like this:
SELECT NEW Result(p, <distance-expression>) FROM MyModel p where <distance-expression> <= :rangeParam order by <distance-expression>
however, i'm afraid that the will be evaluated more than once for each entry and so this will have a negative impact on the runtime/response time of the query.
Is there any way in jqpl to use the AS keyword to avoid the multiple evaluation of
<distance-expression>?
Best regards
A native query with an inner view should get the job done. Assuming class Location(id, latitude, longitude) and the Haversine formula for finding distances between points on great circles, the following repository method declaration with a custom native query should be sufficient:
#Query(nativeQuery = true
, value = "SELECT "
+ " r.id "
+ " , r.latitude "
+ " , r.longitude "
+ "FROM "
+ " (SELECT "
+ " l.id AS id "
+ " , l.latitude AS latitude "
+ " , l.longitude AS longitude "
+ " , 2 * 6371 * ASIN(SQRT(POWER(SIN(RADIANS((l.latitude - ?1) / 2)), 2) + COS(RADIANS(l.latitude))*COS(RADIANS(?1))*POWER(SIN(RADIANS((l.longitude - ?2) / 2)), 2))) AS distance "
+ " FROM "
+ " location l) AS r "
+ "WHERE "
+ " r.distance < ?3")
List<Location> findAllByProximity(BigDecimal latitude
, BigDecimal longitude
, BigDecimal distance);
Sample available on Github as an example (metric units assumed).
Note: The reason behind using a native query in the example as opposed to JPQL is the lack of support for trigonometric functions in JPQL. In cases where the expression is simpler and can be coded using native JPQL functions, the native query can be replaced with a JPA query.

ADO.NET working with SQL and database

I'm getting an exception error saying missing operators can anyone help
string sql = "Select SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate"
+ "From([Orders]"
+ "Inner Join[SalesPerson] On Orders.SalesPersonID=SalesPerson.SalesPersonID)"
+ "Inner Join[Item] On Orders.ItemNumber=Item.ItemNumber"
+ "Where Orders.CustomerID=#customer Order by Orders.OrderDate DESC";
You need to add some spaces at the end of each of your lines of SQL!
string sql = "SELECT SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate "
+ "FROM [Orders] "
+ "INNER JOIN [SalesPerson] ON Orders.SalesPersonID = SalesPerson.SalesPersonID "
+ "INNER JOIN [Item] ON Orders.ItemNumber = Item.ItemNumber "
+ "WHERE Orders.CustomerID = #customer "
+ "ORDER BY Orders.OrderDate DESC";
Otherwise, your SQL ends up being
Select ..... Orders.OrderDateFROM([Orders]Inner Join[SalesPerson] .....
and so on - and that's just not valid SQL.
I also removed some unnecessary parenthesis around the JOIN operators - those are only needed for MS Access, but since you're saying you're using ADO.NET, I assume this is not for MS Access and therefore, those parenthesis are not needed