How to use Oracle TRUNC and NVL function together in JPA Predicate? - java

I have a specific Oracle query that has the following condition in where clause:
SELECT col_a
FROM table_x
WHERE TRUNC(NVL(date_col, sysdate + 365)) >
TRUNC(TO_DATE('11-Jan-2001', 'dd-mon-yyyy'));
I am unable to figure out how to use CriteriaBuilder to create the where clause Predicate. So far, I have figured out a half way but getting stuck at sysdate + 365 part. I specifically need to get DB date as my application current date and DB current date might differ.
Predicate p = criteriaBuilder.greaterThan(
criteriaBuilder.function("TRUNC", LocalDate.class, root.get(date_col)),
criteriaBuilder.function("NVL", LocalDate.class, root.get(date_col))
);
I'm unable to figure out how to get sysdate + 365 and pass it to criteriaBuiler.
Can anyone please help here? I can't post the complete snippet due to corporate restrictions.

Related

Return CURRENT_TIMESTAMP value with specific timezone in Spring data JPA/Hibernate (HQL) query?

I have an Spring Boot API that uses Spring data JPA (1.5.9)/Hibernate (5.0.12) to query my PostgresQL database that is hosted on AWS as a RDS. It is set to Central Time (CST) I have some HQL (Hibernate) queries that use the CURRENT_TIMESTAMP function, but unfortunately and oddly seems to be returning UTC return values for whenever the HQL queries that use CURRENT_TIMESTAMP run.
I need a way to simply force the CURRENT_TIMESTAMP in the HQL query to be central time (CST). I was trying just querying the DB in pure SQL and something like this worked:
CURRENT_TIMESTAMP at TIME ZONE 'America/Chicago'
Unfortunately, I can't seem to get that to work in HQL, as IntelliJ/Hibernate throws a compilation error for:
<expression> GROUP, HAVING, or ORDER expected, got 'AT'
My sample HQL query I am using is:
#Query(value = "SELECT customerCoupons FROM CustomerCouponsEntity customerCoupons "
+ "WHERE customerCoupons.couponCode = :couponCode "
+ "AND customerCoupons.expiredDate >= CURRENT_TIMESTAMP "
+ "AND customerCoupons.startDate <= CURRENT TIMESTAMP "
)
List<CustomerCouponsEntity> findByCouponCode(#Param("couponCode") String couponCode);
Any help would be greatly appreciated. I have the DB set as CST in AWS, so I didn't even expect this CURRENT_TIMESTAMP to be returning a UTC value (still doesn't make sense to me, unless its somehow using the JDBC driver TimeZone or JVM? I mean, this is a Hibernate query, so its not pure SQL right?)
You should try to set the hibernate timezone in your spring boot properties file. Example:
spring.jpa.properties.hibernate.jdbc.time_zone=YOUR_TIMEZONE
Ensure that the value of YOUR_TIMEZONE matches your DB timezone.
I guess this article will help
Posting my own answer;
I tried setting the timezone in the properties/yaml per this article:
https://moelholm.com/blog/2016/11/09/spring-boot-controlling-timezones-with-hibernate
but it did not work no matter what I tried. I made sure I was on hibernate 5.2.3 or greater and it wouldn't work.
I also tried adding the "AT TIMEZONE" in my HQL query but the code wouldn't compile. I guess even though this is valid SQL it doesn't work with the Hibernate SQL queries i.e.
CURRENT_TIMESTAMP at TIME ZONE 'America/Chicago'
Anyway, the only thing that seemed to work was:
#PostConstruct
void started() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}

SQL Query into Hibernate takes infinite time

I am trying to execute an SQL query into Hibernate because of the complexity of it. To do so, I am using the following method:
session.createSQLQuery(sSql).list();
And the SQL query is:
String sSql = "select timestamp, value, space_name, dp_id, dp_description from "+sTable+
" inner join space_datapoint on id = dp_id and timestamp between "+
" (select max(timestamp)-30 day from "+sTable+") and (select max(timestamp) day from "+sTable+")"+
" order by space_name";
The SQL query tries to retrieve a set of values by means of cross references between multiple table/views. The result is a list of objects (different fields from the tables). I have tested the query in the SQL manager of the database and it works. However, when I run it inside the Hibernate framework, it takes a lot of time (I had to stopped the debugger after some minutes, whereas it should take over 5 seconds according to the tests). Do you know what could be the mistake? Or a possible solution?
Thanks a lot in advance,

Getting the totalworkingdays dates through passing the dates dynamically

This is my MySQL database table structure and attendancedate datatype is Date:
attendancedate-------admissionnumber------------attendance
2013-10-03-----------LSTM-0008/2013-2014--------present
2013-10-09-----------LSTM-0008/2013-2014--------present
2013-11-02-----------LSTM-0008/2013-2014--------absent
and i want to disaply like that
monthname---------totalworkingdays---------present----absent
october-------------- 2--------------------2----------0
November--------------1--------------------0-----------1
so am writing the below MySQL query:
select monthname(attendencedate) as monthname,
(select distinct count(*)
from lstms_attendence
where attendencedate>='2013-10-03'
and attendencedate<='2013-10-09'
and addmissionno='LSTM-0008/2013-2014')as totalworkingdays,
sum(CASE WHEN attendence = 'present' THEN 1 ELSE 0 END) as present,
SUM(CASE WHEN attendence = 'absent' THEN 1 ELSE 0 END) AS absent
FROM lstms_attendence
WHERE addmissionno='LSTM-0008/2013-2014' GROUP BY monthname(attendencedate);
But the query is display like this:
monthname---------totalworkingdays---------present----absent
November-----------3-----------------------0------------2
October------------3-----------------------2------------1
please give me the exact query and here am passing dates as hardcoded but that dates are passing dynamically through java to that query.
Let me know the how to create dynamically dates and how to pass values to that query.
Try this:
SELECT
MONTHNAME(attendencedate) as the_month,
COUNT(*) as working_days,
SUM(IF(attendance='present',1,0)) as is_present,
SUM(IF(attendance='absent',1,0)) as is_absent
FROM
lstms_attendence
WHERE
addmissionno='LSTM-0008/2013-2014'
GROUP BY
the_month
Your question doesn't make clear what you're asking. What's wrong with your resultset? Is it the presence of your "november" row?
At any rate, you've got an excessively complex query here, as well as one which will break if you happen to include data from multiple years in it.
Instead of using MONTHNAME(attendancedate), we'll use
DATE_FORMAT(attendancedate, '%Y-%c-01') AS attendancemonth
to figure out in which month an attendancedate lies. This simply turns '2013-11-15' into '2013-11-01', the first day of the month in question. In other words, it truncates (rounds down) the date to the first day of the month.
SELECT admissionnumber,
DATE_FORMAT(attendancedate, '%Y-%c-01') AS attendancemonth,
COUNT(*) AS working_days,
SUM(IF(attendance='present',1,0)) AS is_present,
SUM(IF(attendance='absent',1,0)) AS is_absent
FROM lstms_attendence
WHERE attendancedate >= '2013-10-03'
AND attendancedate < '2013-10-06' + INTERVAL 1 DAY
AND admissionnumber='LSTM-0008/2013-2014'
GROUP BY admissionnumber,attendancemonth
Here is a sqlfiddle.http://sqlfiddle.com/#!2/a2dfb/7/0
This summarizes by both admissionnumber and month, so you can produce a report that contains multiple admissions if you want that.
It uses attendancedate < 'last' + INTERVAL 1 DAY in place of attendancedate <= 'last' because that is robust in cases where attendancedate contains a timestamp other than midnight.
If you need to pass in your parameters from Java, use a prepared statement. Replace the constants in the SQL query with ?, and use setTimestamp and setString. For one example, see JDBC Prepared Statement . setDate(....) doesn't save the time, just the date.. How can I save the time as well?

How do I get CURRENT_DATE in MSSQL?

I am using jpa 3.o with Hibernate. I have one named query:
SELECT COUNT(wt.id) FROM WPSTransaction wt WHERE wt.createdDate>= CURRENT_DATE
WPSTransaction is my entity class and createdDate is one of the columns in my class.
It's working fine in the Mysql Database. However, I'm moving to SQL Server 2012 and SQL server doesn't seem to compile the CURRENT_DATE value. I've tried GETNOW() and NOW() methods as well as current_date() method and CURRENT_TIMESTAMP without any luck.
MS SQL Server fails to conform to the standard here - it does not provide a current_date keyword.
You must instead use the SQL-server specific GETDATE() function, as the document linked shows.
Because current_date is a keyword in the spec, you can't just create a user-defined current_date() function in MS SQL and expect it to work the same. So unfortunately you're stuck with database-specific code here.
The function to return the current date in MS SQL is GETDATE(), so your query should read
SELECT COUNT(wt.id) FROM WPSTransaction wt WHERE wt.createdDate >= GETDATE()
How about:
Query q = entityManager.createQuery("SELECT COUNT(wt.id) FROM WPSTransaction wt WHERE wt.createdDate>= :d");
q.setParam("d", new Date());
No database specific code needed.

how to find difference between two timestamp using hibernate query language

I am trying to write an hql query which gives me the number of hours between two timestamp.
So, far i am unable to do this. I have used hql hour function but that does not work if the
timestamp corresponds to different date. Please provide any input.
My hql query is
select count(*) from com.xxx.Request as request where request.id = :id and hour(current_timestamp - request.lastEventDate) > :delay
well, you can use:
days(first_timestamp) * 24 + hours(first_timestamp)
- days(second_timestamp) * 24 - hours(second_timestamp);

Categories