How to Subtract number of days from current date in HQL query - java

I am using HQL to get the data inserted exact 21 days from now. Here is my Code
Query queryThreeWeek = session.createQuery("from Users where createdDate = CURDATE()-21");
List<Users> userDetailsThreeWeekList = queryThreeWeek.list();
I can not use createSQLQuery.
Right now I am not getting any data, but there is data for the date 2016-06-20. And that is because of the month changed because when I used CURDATE()-7 I got the correct data of the date 2016-07-04.
The calculation for dat is like;
2016-07-11 - 7 = 20160704
2016-07-11 - 21 = 20160690
I also Tired using INTERVAL which is for native sqlQuery. Here is my code for using INTERVAL in HQL:
Query queryThreeWeek = session.createQuery("from Users where createdDate = DATE( DATE_SUB( NOW() , INTERVAL 21 DAY ) )");
List<Users> userDetailsThreeWeekList = queryThreeWeek.list();
Also tried
Query queryThreeWeek = session.createQuery("from Users where createdDate = DATE( DATE_SUB( CURDATE() , INTERVAL 21 DAY ) )");
List<Users> userDetailsThreeWeekList = queryThreeWeek.list();
but it is giving me exception like: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: 21.
So what can I use instead of subtracting the day like this: CURDATE()-21? in HQL only

I have solved the issue by using one native SQL query which can get me the exact date.
Query sub3Week = session.createSQLQuery("select DATE( DATE_SUB( CURDATE() , INTERVAL 21 DAY ) ) from dual");
List<Date> sub3WeekList = sub3Week.list();
And then I use this data in the HQL query like this:
Query queryThreeWeek = session.createQuery("from Users where createdDate = :createdDate");
queryThreeWeek.setParameter("createdDate", sub3WeekList.get(0).toString());
List<Users> userDetailsThreeWeekList = queryThreeWeek.list();

You can use date_Sub in a native SQL query (not a HQL query!):
"from Users where createdDate = DATE( DATE_SUB( NOW() , INTERVAL 21 DAY ) )"

The solution with HQL is quite simple:
final long time = System.currentTimeMillis() - java.time.Duration.ofDays(21).toMillis();
final javax.persistence.Query query = entityManagerOrSession.createQuery(
"SELECT x FROM users x WHERE x.createddate> :time");
query.setParameter("time", new java.sql.Timestamp(time));

Related

Hibernate - filter Single Column data using date where clause

Lets say One table ABC having two column i.e. ID & CREATED_DATE
I want to fetch those ID which is created lets say '09-11-2017' and '09-17-2017'
Below SQL query working fine but I want to implement same logic using hibernate.
select ID from ABC where between TO_DATE('09-11-2017', 'MM-DD-YYYY') AND TO_DATE('09-17-2017', 'MM-DD-YYYY')
My code is not working.
public List getData(final Date startDate, final Date endDate){
String sqlString = "select ID from ABC where CREATED_DATE between :startDate and :endDate";
SQLQuery query = getSession().createSQLQuery(sqlString);
query.setParameter(CREATED_DATE);
return query.list();
}
You are missing End date parameter :
query.setParameter(CREATED_DATE, startDate);
query.setParameter(END_DATE, endDate);
It not work because you don't set the correct parameters :
String sqlString = "select ID from ABC where CREATED_DATE between :startDate and :endDate";
SQLQuery query = getSession().createSQLQuery(sqlString);
query.setParameter("startDate ", start_date);
query.setParameter("endDate", end_date);
return query.list();
The parameters must match the string on the query
Try this:
public List getData(final Date startDate, final Date endDate){
String sqlString = "select ID from ABC where CREATED_DATE between :startDate and :endDate";
SQLQuery query = getSession().createSQLQuery(sqlString);
query.setParameter("startDate",startDate);
query.setParameter("endDate",endDate);
return query.list();
}
--
pscar13

QueryDSL group by hours in a time range

I have the following SQL query to group orders by the order date and hour in a day:
select to_char(o.order_date, 'YYYY-MM-DD HH24') order_date_hour,
sum(o.quantity) quantity
from orders o
where o.order_date >= to_date('01.02.2016', 'DD.MM.YYYY')
and o.order_date < to_date('03.02.2016', 'DD.MM.YYYY')
group by to_char(o.order_date, 'YYYY-MM-DD HH24')
order by to_char(o.order_date, 'YYYY-MM-DD HH24');
An example for the result is as follows:
ORDER_DATE_HOUR | QUANTITY
2016-02-01 06 | 10
2016-02-03 09 | 20
The query works as expected using SQL developer.
In QueryDSL I came up with the following query:
SQLQuery q = queryFactory.createSQLQuery();
q.from(order);
q.where(order.orderDate.goe(Timestamp.valueOf(from)))
.where(order.orderDate.lt(Timestamp.valueOf(to)));
q.groupBy(to_char(order.orderDate, "YYYY-MM-DD HH24"));
q.orderBy(order.orderDate.asc());
List<Tuple> result = q.list(to_char(order.orderDate, "YYYY-MM-DD HH24"), order.quantity);
to_char is a method I found in this thread: https://groups.google.com/forum/#!msg/querydsl/WD04ZRon-88/nP5QhqhwCUcJ
The exception I get is:
java.sql.SQLSyntaxErrorException: ORA-00979: not a GROUP BY expression
I tried a few variations of the query with no luck at all.
Does anyone know why the query is failing?
Thanks :)
You can use StringTemplate and DateTemplate to build custom expressions, like done in the unit test com.querydsl.sql.TemplateTest:
StringTemplate datePath = Expressions.stringTemplate(
"to_char({0},'{1s}')", order.orderDate, ConstantImpl.create("YYYY-MM-DD HH24"));
DateTemplate from = Expressions.dateTemplate(
Date.class, "to_date({0},'{1s}')", fromStr, ConstantImpl.create("DD.MM.YYYY"));
DateTemplate to = Expressions.dateTemplate(
Date.class, "to_date({0},'{1s}')", toStr, ConstantImpl.create("DD.MM.YYYY"));
query.select(datePath.as("order_date_hour"), order.quantity.sum().as("quantity"))
.from(order)
.where(order.orderDate.goe(from)
.and(order.orderDate.lt(to)))
.groupBy(datePath)
.orderBy(datePath.asc());
List<Tuple> results = query.fetch();
Here the printout for query.getSQL().getSQL():
select to_char("order".order_date,'YYYY-MM-DD HH24') order_date_hour, sum("order".quantity) quantity
from "order" "order"
where "order".order_date >= to_date(?,'DD.MM.YYYY') and "order".order_date < to_date(?,'DD.MM.YYYY')
group by to_char("order".order_date,'YYYY-MM-DD HH24')
order by to_char("order".order_date,'YYYY-MM-DD HH24') asc

Java JPA Queries

i'm trying to select all enteties from a databse where a certain date is older than 7 days. It works fine via SQLyog, but in Java it always throws this error:
[33, 76] The expression is not a valid conditional expression.
[76, 101] The query contains a malformed ending.
This is my query in Java:
SELECT a FROM Applicants a WHERE (a.lastMod <= CURRENT_DATE - INTERVAL 7 DAY) ORDER BY a.applDate ASC
May the problem be the "CURRENT_DATE"-part?
CURRENT_DATE is ok, but INTERVAL 7 DAY is not a valid JPQL expression. You'll need to supply the date as parameter
WHERE a.lastMod <= :dateParam
Example:
Query q = em.createQuery("SELECT a FROM Applicants a WHERE a.lastMod <= :dateParam ORDER BY a.applDate ASC");
q.setParameter("dateParam", dateParam);
List<Applicants> applicants = (List<Applicants>)q.getResultList();
// or, to avoid casting (thanks to #DavidSN)
TypedQuery<Applicants> q = em.createQuery("SELECT a FROM Applicants a WHERE a.lastMod <= :dateParam ORDER BY a.applDate ASC", Applicants.class);
q.setParameter("dateParam", dateParam);
List<Applicants> applicants = q.getResultList();
EntityManager em = ...
Query q = em.createQuery ("SELECT a FROM Applicants a WHERE a.lastMod <= :dateParam");
q.setParameter("dateParam" , dateParam);
List<blabla> results = q.getResultList ();

Compare timestamp date in Postgresql in java

I am using PostgreSQL database & JPA. Here is my user table
CREATE TABLE users
(
id integer NOT NULL DEFAULT nextval('userseq'::regclass),
firstname character varying(64) ,
middlename character varying(64),
lastname character varying(64),
birthdate timestamp with time zone,
)
Query query = em
.createQuery(
"SELECT users FROM Users users WHERE user.birthdate =:a")
.setParameter("a",18)
.setParameter("b",25);
query.getResultList();
I want get all user whose age in between 18-25. Please complete my above JPA query
Use Between operator, fix to user.birthdate to users.birthdate at first.
Calendar cal_1 = Calendar.getInstance();
cal_1.add(Calendar.YEAR, -18);
Date a = cal_1.getTime();
Calendar cal_2 = Calendar.getInstance();
cal_2.add(Calendar.YEAR, -25);
Date b = cal_2.getTime();
query.setParameter("a", a);
query.setParameter("b", b);
SELECT users FROM Users users WHERE users.eventsDate BETWEEN :a AND :b
Example : x BETWEEN :min AND :max. Reference here
JPQL is lacking in date operators. In SQL you'd write something like:
SELECT age(TIMESTAMPTZ '1999-01-01') BETWEEN INTERVAL '18' YEAR AND INTERVAL '25' YEAR;
but you can't do that in JPQL as far as I can tell. BETWEEN is supported in JPQL, so I'd convert the date parameters a and b to java.util.Date using java.util.Calendar, then use:
SELECT users FROM Users users WHERE user.birthdate BETWEEN :a AND :b

Doing a query for each day in a period, turning it into one query

I have this:
public Map<Day,Integer> getUniqueLogins(long fromTime, long toTime) {
EntityManager em = emf.createEntityManager();
try {
Map<Day,Integer> resultMap = new ...;
for (Day day : daysInPeriod(fromTime, toTime)) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> q = cb.createQuery(Long.class);
// FROM UserSession
Root<UserSession> userSess = q.from(UserSession.class);
// SELECT COUNT(DISTINCT userId)
q.select(cb.countDistinct(userSess.<Long>get("userId")));
// WHERE loginTime BETWEEN ...
q.where(cb.between(userSess.<Date>get("loginTime"), day.startDate(), day.endDate()));
long result = em.createQuery(q).getSingleResult();
resultMap.put(day, (int) result);
}
return resultMap;
} finally {
em.close();
}
}
This executes a query for each day in a given period (the period being in the order of magnitude of a month).
Could I get this specific data in one query? I'm using Hibernate/MySQL, but I'd prefer not to need any non-standard functions.
Assuming your original query is:
SELECT COUNT(DISTINCT userId)
FROM UserSession
WHERE loginTime BETWEEN dayStart AND dayEnd;
This should return the same results as running the original one per each day of the period:
SELECT date(loginTime) AS day, COUNT(DISTINCT userId)
FROM UserSession
WHERE loginTime BETWEEN startDate AND endDate
GROUP BY day;
GROUP BY the date segment of LoginTime counting distinct userids. The back-end should provide a way to extract the date-part of the datetime value.
You'll have to use MySQL specific functions to do this.
SELECT FROM_DAYS(TO_DAYS(loginTime)) AS day, COUNT(DISTINCT userId)
FROM UserSession
WHERE loginTime BETWEEN :fromTime AND :toTime
GROUP BY day
The from_days/to_days will convert the loginTime to a number of days and then back to a datetime but with the hour/minute/second parts zero'd.

Categories

Resources