I am writing a Springboot JPA REST API that talks to DB2 database and should query a table containing a TIMESTAMP
field.
Using SQL, the DB2 query to filter rows between two TIMESTAMPs would be like below and it will return 1 record from my test data:
SELECT * FROM CARS WHERE SOLD_DATE BETWEEN '2020-01-01' AND '2022-01-01'
Since I am using Spring Data JPA, I have defined CarEntity
which has a java.sql.Timestamp
field
@Entity
public class CarEntity {
....
Timestamp soldDate;
...
//getters and setters
}
I am trying to retrieve data like in above SQL query.
To do so, I pass the start and end data in Postman as Long
values representing start and end date through URL like
http://localhost:8080/cars/sold/1420070400/1640995200
This endpoint hits my controller method which converts the Long
into java.sql.Date
and passes it to repository and in repository, I use @Query
annotation like below:
@Repository
public interface CarRepository extends JpaRepository<CarEntity, Timestamp>{
@Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between :startDate and :endDate")
List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);
}
However, this does not work and it returns no data although I know it should return me 1 record.
But if I hardcode the start and end date like below, I get the 1 record:
@Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between '2020-01-01' and '2022-01-01'")
List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);
Of course, problem with that is that I hardcoded startDate and endDate instead of using the ones passed into getCarsSoldBetween()
method.
UPDATE-1
Thanks to @HYUNJUN, I added couple of changes:
java.sql.Timestamp
in my Entity like before but my
Controller, Service, and Repository use java.util.Date
instead of
java.sql.Date
which I was using initially.logging.level.org.hibernate.sql=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
Now, when I go to DB2 Bench and issue following query, I will get 2 rows back which is correct:
SELECT * FROM MYSCHEMA.CARS WHERE SOLD_TIMESTAMP BETWEEN '2021-10-04 15:00:00' AND '2021-10-20 00:00:00';
// RETURNS 2 ROWS
However, my repository query which looks like:
@Repository
public interface CarRepository extends JpaRepository<CarEntity, Timestamp>{
@Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between :startDate and :endDate")
List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);
}
, returns nothing and I would expect to return 2 rows since the start and end date are same as per the logging output:
type.descriptor.sql.BasicBinder binding parameter [1] as [TIMESTAMP] - [Mon Oct 04 15:00:00 PDT 2021]
type.descriptor.sql.BasicBinder binding parameter [2] as [TIMESTAMP] - [Wed Oct 20 00:00:00 PDT 2021]
So, I am passing the same date range and would expect the same result, but that is not happening
The following recommendations will help you in your SQL tuning process.
You'll find 3 sections below:
ALTER TABLE `CARS` ADD INDEX `cars_idx_sold_date` (`SOLD_DATE`);
SELECT
*
FROM
CARS
WHERE
CARS.SOLD_DATE BETWEEN '2020-01-01' AND '2022-01-01'