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.
Related
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"));
}
I have a following JPA query:
#Query(value = "select r FROM TableEntity r where r.time=?1")
TableEntity findByTime(java.sql.Timestamp time);
That query is pretty straightforward, should fetch the database row based on some time. It works like a charm with MYSQL and Oracle but won't work for MSSQL. I have debugged the query through Hibernate and JTDS driver and saw that Timestamp is successfully resolved in the Prepared statement, I can see the exact number of hours, minutes, seconds and milliseconds in query as I have in the database row. However, no data is returned back.
class TableEntity {
#Type(type = "timestamp")
private Timestamp time;
}
I am suspecting that some milliseconds rounding happens or they somehow gets messed up since query does return something once in a blue moon!
My Time Field in the database is datetime2(3)
I am using the net.sourceforge.jtds 1.3 driver.
Time is formatted like this: 2020-06-03 13:02:21.273, I am working with milliseconds
EDIT:
I tried writing plain prepared statement and here are results:
select r FROM TableEntity r where r.time=?1
preparedStatement.setTimestamp(1, timestamp); //does not work...
preparedStatement.setString(1, timestamp.toString()) //works like a charm
Any idea?
So, under the hood, Hibernate was mapping that timestamp to datetime type when it queried the DB (I concluded that using the MSSQL profiler) . Since I had datetime2 in the DB, comparing datetime with datetime2 on the DB level was not returning anything even if they were exactly the same in Milliseconds.
Solution would be to force mapping of timestamp to datetime2 so db datetime2 type gets queried with the same type
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.
id name date
1. ask 2018-04-25 12:30:59
2. msk 2018-04-25 12:40:43
3. sdf 2017-05-25 12:42:34
id=int---->in java id-->int
name=varchar(25)----> in java name-->string
date=datetime------->in java date--->Timestamp
my sql query=select * from table where year(date)='2018';
o/p:1. ask 2018-04-25 12:30:59
2. msk 2018-04-25 12:40:43
select * from table where month(date)='05'
o/p:3. sdf 2017-05-25 12:42:34
please help me i dont know
how to write this query in hibernate
How to write the above queries in hibernate? I have tried lot things but I didn't get any solution. If I use to_char() in hibernate it will give a unexpected token error.
You do not have to use to_char() function. Hibernate supports year and date functions.
Refer this link: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html
and look under "14.10. Expressions".
So your hql would simply look like this:
select t from table t where YEAR(t.date)='2018';
and select t from table t where MONTH(t.date)='05';
there is no need to use to_char() method here. you can simply use this query inside your Dao Implementation class.
for years:
session.createSQLQuery("select * from table where year(date) = :year")
.setParameter("year",2018)
.list();
for Months
session.createSQLQuery("select * from table where month(date) = :month")
.setParameter("month",05)
.list();
I need to retrieve from my PostgreSQL database, which has been mapped to Java using Hibernate, the average difference of dates (start and end, as you may say) of the records.
I wrote a native PostgreSQL query which works fine:
SELECT avg(date_part('days', age(datasaida, dataentrada))) as avg_days
FROM processo.processo
WHERE processo.codsituacao = '14'
AND processo.dataEntrada >= now() - interval '30 days';
The problem is that I can't figure out how to translate this query to HQL (Hibernate SQL) because of the avg(date_part('days', age(datasaida, dataentrada))) part.
I need the information to be shown in the front-end, which I am building with JSF Primefaces.
P.S.: dataEntrada - means startDate (kind of). dataSaida means endDate (kind of)
You could try
avg(DAY(function('age', datasaida, dataentrada)))
or
avg(DAY(datasaid - dataentrada))
DAY is standard JPA function: http://www.objectdb.com/java/jpa/query/jpql/date
And with function('age', datasaida, dataentrada) you call a database specific function from JPA
Well you can use function('function_name', param1, param2) in the HQL to call the native Postgresql functions:
SELECT avg(function('date_part', 'days', function('age', datasaida, dataentrada))) as avg_days
FROM processo.processo
WHERE processo.codsituacao = '14'
AND processo.dataEntrada >= now() - interval '30 days';
For further details you can check the Call PostgreSQL-specific SQL Functions section of the Hibernate with PostgreSQL – 6 things you need to know tutorial.