Java JPA Queries - java

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 ();

Related

Spring Boot, JPA / Hibernate: How to execute two raw SELECT queries at once?

When I try to execute two SELECT statements at once as follows below, the logging console returns a runtime error:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT * FROM ...
The Java source code that generates the statements:
#Repository
public class VehicleObjectDbAccess {
#PersistenceContext
EntityManager entityManager;
public List<Object[]> getObjectById(long objectId, long year)
{
int limit = 10;
String tableName = ("i0i"+year)+objectId;
String queryText =
"START TRANSACTION;"
+ "SELECT t.created INTO #startTime FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1;"
+ "SELECT * FROM ObjectTable WHERE created <= (CASE WHEN #startTime IS NULL THEN NOW() ELSE #startTime END) ORDER BY created DESC LIMIT 10;"
+ "COMMIT;";
Query query = this.entityManager.createNativeQuery(queryText);
return query.getResultList();
}
}
Eventually the java source code above translates to
START TRANSACTION;
SELECT t.created INTO #startTime FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1;
SELECT * FROM ObjectTable WHERE created <= (CASE WHEN #startTime IS NULL THEN NOW() ELSE #startTime END) ORDER BY created DESC LIMIT 10;
COMMIT;
I verified that SQL code running it on a MySQL client and it works properly.
How can I execute these two SELECT statements in a single query?
It seems you can divide your compound sql query to two separate SELECT queries:
Query query1 = this.entityManager.createNativeQuery(queryText1);
Query query2 = this.entityManager.createNativeQuery(queryText2);
After that you can get result lists from them and add result lists to one compound List:
List<Object[]> result = new ArrayList<>();
result.addAll(query1.getResultList());
result.addAll(query2.getResultList());
Just use one select statement:
SELECT *, (SELECT t.created FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1) as x FROM ObjectTable WHERE created <=
(CASE WHEN x IS NULL THEN NOW()
ELSE x
END)
ORDER BY created DESC LIMIT 10;
If you don't want to do this for some reason, create a stored procedure that returns a result set and call it...

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

Inner join query on Hibernate - SQL queries do not currently support iteration

I'm new to hibernate and I've this SQL query which works perfectly
SELECT count(*) as posti_disponibili from occupazione t inner join
(select id_posto_park, max(date_time) as MaxDate from occupazione
group by id_posto_park) tm on t.id_posto_park = tm.id_posto_park and
t.date_time = tm.Maxdate and t.isOccupied = 0
which gives me all the last items with isOccupied = 0
I was porting it into Hibernate, I've tried to use
result = ( (Integer) session.createSQLQuery(query).iterate().next() ).intValue()
to return posti_disponibili but i got this exception
java.lang.UnsupportedOperationException: SQL queries do not currently support iteration
How can i solve this? I cannot find the equivalent HQL query
Thank you
I would suggest you to use
Query#uniqueResult()
which will give you single result.
select count(*) .....
will always return you a single result.
Hibernate support it's own iterator-like scroll:
String sqlQuery = "select a, b, c from someTable";
ScrollableResults scroll = getSession().createSQLQuery(sqlQuery).scroll(ScrollMode.FORWARD_ONLY);
while (scroll.next()) {
Object[] row = scroll.get();
//process row columns
}
scroll.close();

HQL where clause with variable inserted

I need to insert a variable into an existing HQL where clause as follows:
java.sql.Timestamp currentDate = new Timestamp(System.currentTimeMillis());
Query q = em.createQuery("from fAdjustmentReason a where a.startDate >= " + currentDate + " and a.endDate <= " + currentDate);
I get the following error message when I do the above:
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: 18 near line 1, column 79
[from gov.va.med.domain.fee.AdjustmentReason a where a.startDate >= 1969-12-31 18:00:00.0 and a.endDate <= 1969-12-31 18:00:00.0]
Should I just add a currentDate field to the existing AdjustmentReason model class even though it's not in the DB to make this more straightforward?
Any help is GREATLY appreciated!
As you are creating Query object, you should use setParameter to set the dates in your query eg.
Query q = em.createQuery("from fAdjustmentReason a where a.startDate >= :0 and a.endDate <= :1");
q.setParameter(0,dateFrom);
q.setParameter(1,dateFrom);
That is the reason of prepared statement.
Complete example can be found here
This way your are doing its not the best way, it makes you code vulnerable to SQL injection, the correct way of doing it and solving your problem is the following:
Query q = em.createQuery("from fAdjustmentReason a where a.startDate >= :startDate and a.endDate <= :endDate")
.setParameter("starDate", currentDate)
.setParameter("endDate", currentDate)
Hope it helps!

JPA Criteria Group By

I have got the following problem, maybe somebody can help me.
I wrote a SQL query:
SELECT v.bezeichnung, count(*) as total
FROM veranstaltung v
JOIN auffuehrung a ON v.id = a.veranstaltung_id
JOIN platz p ON p.auffuehrung_id = a.id
JOIN transaktion t ON t.id = p.transaktion_id
WHERE t.status = 2 AND (a.datumuhrzeit + 30 DAY) >= CURRENT_DATE
GROUP BY v.bezeichnung
ORDER BY total DESC
I have to implement it in JPA but everything works except GROUP BY... it can't be grouped..
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Veranstaltung> query = builder.createQuery(Veranstaltung.class);
Root<Veranstaltung> rootVeranstaltung = query.from(Veranstaltung.class); query.where(builder.equal(rootVeranstaltung.join("auffuehrungen").join("plaetze").join("transaktion").<Transaktionsstatus>get("status"), Transaktionsstatus.BUCHUNG));
query.groupBy(rootVeranstaltung);
List<Veranstaltung> result = this.entityManager.createQuery(query).getResultList();
return list;
I haven't finished the code yet, e.g. the COUNT..
should i write COUNT already before GROUP BY or would it work without COUNT?

Categories

Resources