Wrong type returned for aggregate functions over date? [message #1856781] |
Mon, 02 January 2023 08:54  |
Morten Torp Meiling Messages: 3 Registered: May 2022 |
Junior Member |
|
|
Hi
I have a strange problem. I am trying to create a query that returns the MIN of a date field that I have in an @Entity. The field has the Instant java type.
I have an attribute converter in place that handles instants by converting them to LocalDateTime in UTC (since JPA/Eclipselink handles LocalDateTime, and does not support Instants). It should be noted that the dates are saved to an datetime2 column in SQL Server (so it does not have offset information).
This approach works just fine for everything but aggregate functions. So if I have a query that selects MIN or MAX over some field that is mapped to Instant in my entity, the result is a Timestamp and I get a ClassCastException when it tries to use my converter (as that expects a LocalDateTime).
My converter looks as follows:
@Converter(autoApply = true)
public class InstantAttributeConverter implements AttributeConverter<Instant, LocalDateTime> {
@Override
public LocalDateTime convertToDatabaseColumn(Instant instant) {
return instant == null ? null : LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), ZoneOffset.UTC);
}
@Override
public Instant convertToEntityAttribute(LocalDateTime localDateTime) {
return localDateTime == null ? null : localDateTime.toInstant(ZoneOffset.UTC);
}
}
A simplified example of how I create a query using Criteria API
taskState = root.join(PendingTasksTrigger_.state, JoinType.INNER);
tasks = taskState.join(TaskState_.tasks, JoinType.INNER);
criteriaQuery.select(
criteriaBuilder.construct(TaskDeadline.class,
taskState.get(TaskState_.id),
tasks.get(Task_.creationDate),
criteriaBuilder.least(tasks.get(Task_.deadline)))
);
criteriaQuery.groupBy(taskState.get(TaskState_.id), tasks.get(Task_.creationDate));
So a TaskState has a "tasks" collection that I use in the join, and the deadline is an Instant in the Task entity.
And the error that I get when it tries to invoke my converter:
Caused by: java.lang.ClassCastException: class java.sql.Timestamp cannot be cast to class java.time.LocalDateTime
|
|
|
|
Re: Wrong type returned for aggregate functions over date? [message #1856864 is a reply to message #1856782] |
Fri, 06 January 2023 00:43  |
Chris Delahunt Messages: 43 Registered: December 2021 |
Member |
|
|
I don't know if there are any changes since 2.7.8 that touch on LocalDateTime support, but usually easier to try it out.
What is the database type under the column? I don't understand the problem with toString logic in java.sql.Timestamp - EclipseLink I believe will be converting your data to/from a Timestamp to bind it to the statement, so having an intermediary LocalDateTime conversion seems unnecessary. date/time is just a long value - LocalDateTime is heavily influenced by timezone, and will do conversations from the local Instant 'long' value based on the timezone and why you have to deal with ZoneOffset.UTC in your conversions to/from an instant. Timestamp is just another wrapper over the long value used within Instant, so be less overhead to convert and should be functionally equivalent to what you are doing now.
Best Regards,
Chris
[Updated on: Fri, 06 January 2023 00:44] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.01592 seconds