Query that works in oracle and HSQL - java

Hello all I have a query in my code which is working with oracle 12c.
SELECT *
FROM TABLE-A
join TABLE-B on TABLE-A.id=TABLE-B.id
where TABLE_B.ISRT_TS BETWEEN TO_TIMESTAMP ('10-JUN-17 04.00.00.000000000 AM','DD-Mon-RR HH:MI:SS.FF9 AM') AND TO_TIMESTAMP('10-Sep-17 03.59.59.999999999 AM', 'DD-Mon-RR HH:MI:SS.FF9 AM')
but when I execute same query in HSQL I am getting exception. can any one suggest what to change in the existing query to work in oracle and hsql.
Error in hsql:data exception: invalid datetime format: 9 AM
Elapsed Time: 0 hr, 0 min, 0 sec, 0 ms.
HQL vesrsion: 1.8.0.10

to_timstamp() is not part of the SQL standard, so it's not a surprise that HSQL does not understand it.
A portable way of writing your condition is to use ANSI timstamp literals:
select *
from table_a
join table_b on table_a.id = table_b.id
where table_b.isrt_ts between timestamp '2017-06-10 04:00:00' and timestamp '2017-09-10 03:59:59.99999'
I don't know if the ancient and outdated version 1.8 supports that - but you should really upgrade to a current version.

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"));
}

How do I convert between org.hibernate.type.TimestampType and Oracle SYSDATE?

I have a column that is mapped in hibernate using org.hibernate.type.TimestampType. How can I use native Oracle SQL to store and retrieve these values based on an Oracle TIMESTAMP?
The column is mapped as NUMBER(10). I tried using some formulas I found for Unix timestamps, but they did not seem to produce the correct results.
Here is a recent timestamp:
1579730473525
This would have been some date within the last 2-3 weeks (Jan 2020).
Details
I want to use Hibernate Envers, with the ValidityAuditStrategy. I'm running into trouble because I'm applying Envers to a database of existing records that have no audit history. What I'm trying to do is do a one-time insert of audit data, using Oracle SYSDATE as the timestamp.
I wasn't sure what format your number 1579730473525 was in, so I took a guess and took the first 10 digits using a SUBSTR, and the result was a reasonable 2020 date as follows.
SELECT TO_DATE('1970-01-01','YYYY-MM-DD') +
NUMTODSINTERVAL(TO_NUMBER(SUBSTR('1579730473525',1,10)), 'SECOND') FROM dual;
returns
22/01/2020 22:01:13
Then to get the TIMESTAMP, I added the last 4 digits.
SELECT to_char(TO_DATE('1970-01-01','YYYY-MM-DD') +
NUMTODSINTERVAL(TO_NUMBER(SUBSTR('1579730473525',1,10)), 'SECOND') ,'YYYY-MM-DD hh:mm:ss') ||'.'||SUBSTR('1579730473525',10,4)
FROM dual;
and this returns:
2020-01-22 10:01:13.3525
(I couldn't find a way of directly converting the 14 digit number back to a YYYY-MM-DD hh:mm:ss:ff format; it complained of precision)
Then to get the number into TIMESTAMP format:
SELECT TO_TIMESTAMP(TO_CHAR(TO_DATE('1970-01-01','YYYY-MM-DD') +
NUMTODSINTERVAL(TO_NUMBER(SUBSTR('1579730473525',1,10)), 'SECOND') ,'YYYY-MM-DD hh:mi:ss') ||'.'||SUBSTR('1579730473525',10,4),'YYYY-MM-DD hh:mi:ss:ff')
FROM dual;
and this returns it in the Oracle TIMESTAMP as requested, using Oracle SQL.
Just a hint: if you leave out formatting, make a note of your NLS parameter NLS_TIMESTAMP_FORMAT in case you get formatting issues.

HSQLDB Unexpected token: GETDATE

JPA & Hibernate application uses HSQLDB for JUnit tests.
HSQLDB 1.8.0
Hibernate 3.2.4.sp1
Java 7
While the tests worked fine against an Oracle database, getting the following error now that we are using MSSQL 2016:
Unexpected token: GETDATE in statement [select ..... effective_date < GETDATE() AND ... ]
So I understand that HSQL uses SYSDATE, CURDATE, or NOW instead of the MSSQL GETDATE function, and I've done the following:
Attempted to set sql.syntax_mss to true by URL and SQL statement:
public static final String HYPERSONIC_JDBC_URL = "jdbc:hsqldb:mem:aname;sql.syntax_mss=true";
entityManager.createNativeQuery("set database sql syntax MSS true").executeUpdate();
Register the function in the Dialect and/or create a function:
registerFunction("GETDATE", new NoArgSQLFunction("SYSDATE", new DateType()));
entityManager.createNativeQuery("CREATE FUNCTION GETDATE() RETURNS DATE RETURN CURDATE()").executeUpdate();
None of this seems to have any effect.
Live application is connected to MS SQL Server 2016 via mssql-jdbc-6.2.1.jre7 driver.
So while upgrading the libraries as #fredt mentioned in the comments is probably the best route, upgrading hsqldb.jar breaks dbunit.jar, upgrading that breaks.. etc.
Was able to remove the GETDATE occurrences and fix the sequence generation strings (select next value for seq_name from seq_name is the format it likes) and now we are back to a working state.
Upgrading these libraries can be put in the bucket with upgrading jBoss, Hiberate, jBPM and Quartz :)

How can I query the average difference of dates in days using HQL (Hibernate)?

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.

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.

Categories