how to use alias in querydsl? - java

I am new to querydsl and already in love with it, but I can't get how to use an alias in this query.
QProduct product = QProduct.product;
JPQLQuery jPQLQuery =
from(product)
.where(product.name.locate(searchTerm).as("score").gt(0).or(product.code.locate(searchTerm).as("score").gt(0))).groupBy(product.baseProd);
List<Product> matchedNames = jPQLQuery.orderBy(new NumberPath<Integer>(Integer.class, "score").asc()).offset((pageNumber-1)*10).limit(10).list(product);
my first thought was something like this which throws an error with the generated query as:
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token:
as near line 3, column 31 [select product from
mesoft.meshopframework.model.Product product where
locate(?1,product.name) as score > ?2 or locate(?1,product.code) as
score > ?2 group by product.baseProd order by score asc]
could someone show me the coorect way to do this?? I hope it's not necessary for DB to calculate product.name.locate(searchTerm) or the other one again for sorting,
thanks

JPQL has a more restricted syntax compared to SQL, but I don't think your example would work in SQL either.
You can't use aliases in the where part and for order you will need pick one of the locate expressions or order by both of them.

Related

#query to get record with max date

I have a mysql table called sp_500. Each record has a unique date. I want the last record in the table. It will have the max date. What is the best query to pull it? I tried the following HQL:
public interface QuoteRepository extends JpaRepository<Quote, Long> {
#Query("from sp_500 a where a.date in (select max(b.date) from sp_500 b)")
Quote getQuote(String symbol);
}
but when I run it, the following error is displayed:
Caused by: java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: sp_500 is not
mapped [from sp_500 a where a.date in (select max(b.date) from sp_500
b)]
Suggestions?
Can be done in two ways using the ORDER BY
1)
*Best practice
You can SELECT TOP 1 with the ORDER BY date desc.
Removing the MAX part of you QUERY
//If you are using ORACLE i think is ROW COUNT = 1
2)
You can make the SELECT * ... ORDER BY date desc
and just grab the first register
Thanks to #Nick and #luisfa19. You gave me valuable clues. Here is what worked:
#Query(value="select * from sp_500 order by date desc limit 1", nativeQuery = true)

join and where clause in hibernate

I am using join and where clause in hibernate 3.but i cant reach the solution.I got the error.
Query qry= session.createQuery("SELECT addemployee.eid,addemployee.fname,addemployee.location,"
+ "empdet.jtitle,empdet.leadname FROM addemployee LEFT JOIN empdet ON addemployee.eid = empdet.eid WHERE (addemployee.eid ='"+id+"')");
List l = qry.list();
Iterator it=l.iterator();
while(it.hasNext())
{
Object rows[] = (Object[])it.next();
System.out.println(rows[0]+separator+rows[1]+separator+rows[2]+separator+rows[3]+separator+rows[4]);
}
Issue: org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ON near line 1, column 127 [SELECT addemployee.eid,addemployee.fname,addemployee.location,empdet.jtitle,empdet.leadname FROM addemployee LEFT JOIN empdet ON addemployee.eid = empdet.eid WHERE (addemployee.eid ='206')]
Try to use session.createSQLQuery() instead.
and don't put enclosed apostrophe (''), you are inputting numbers, not varchar.
like this.
Query qry= session.createSQLQuery("SELECT addemployee.eid,addemployee.fname,addemployee.location,"
+ "empdet.jtitle,empdet.leadname FROM addemployee LEFT JOIN empdet ON addemployee.eid = empdet.eid WHERE (addemployee.eid ="+id+")");
Hibernate Session's createQuery() method requires valid HQL syntax. You can check how to write joins here.
Basically, in HQL you work with your entities, not SQL tables. So you don't need to write ON, because you already map association between entities.
If you still want to write native SQL query, you need to use
session.createSQLQuery(); instead

Hibernate 4 Distinct and order by together

select distinct groupMember.proUcer.proUserDetail
from proGroupMembership groupMember
where groupMember.proGroup.id =:groupId and groupMember.status = 1
order by groupMember.proUcer.proUserDetail.firstName
ORA-01791 Exception
coming when i execute this Query.
After many research i got solution to solve this problem by selecting one more column on which we are applying order by -
So i convert query according that solution
select distinct groupMember.proUcer.proUserDetail, groupMember.proUcer.proUserDetail.firstName
from proGroupMembership groupMember
where groupMember.proGroup.id =:groupId and groupMember.status = 1
order by groupMember.proUcer.proUserDetail.firstName
Now my problem is I only need list of object but query.list() returning list of array of object.
Please help me to solve this problem.
Don't repeat yourself in the query like that. Use joins:
select distinct proUserDetail
from proGroupMembership groupMember
join groupMember.proUcer proUcer
join proUcer.proUserDetail proUserDetail
where groupMember.proGroup.id = :groupId and groupMember.status = 1
order by proUserDetail.firstName

HQL - COUNT on SELECT clause not working

I'm trying to create an HQL query that calculates several stats on a list on specific users for specific dates (for example, how many were logged in etc.). Each stat has a different criteria):
SELECT
COUNT(SELECT u2.id FROM User u2 WHERE u.id = u2.id AND u2.lastLoginDate BETWEEN x AND y),
COUNT(some other stats), ...
FROM User u
WHERE u.managerId IN (...)
While the COUNT(SELECT...) clause worked in MySQL, in HQL I get the following exception:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: SELECT
Anyone know how to make it work?
EDIT:
Ok, So according to this suggestion HQL - COUNT on SELECT clause not working now the query looks something like this:
SELECT
COUNT(DISTINCT CASE WHEN u.lastLogin BETWEEN x AND y THEN u.id ELSE null END),
COUNT(DISTINCT CASE WHEN ... END),
SUM(CASE WHEN u.id = p.userId THEN p.amount ELSE null END),
FROM User u, Points p,... WHERE u.managerId IN (...)
Problem is, the calculated SUM is not correct because of the From clause - it's multiplied by the number of tables.
For example if the total sum should be 80, and I have 4 tables in the from clause, the sum is instead 480!
Obliviously, distinct won't work correctly for sum. Any ideas?
It seems that you just want conditional aggregation. It is unclear what you really want from the query, but this may be close:
SELECT COUNT(*) as cnt1,
SUM(CASE WHEN u2.lastLoginDate BETWEEN x AND y THEN 1 ELSE 0 END) as cnt2,
SUM(CASE WHEN some other stats THEN 1 ELSE 0 END), ...
FROM User u
WHERE u.managerId IN (...)
I am surprised that count(select . . . ) worked in MySQL. First, subqueries usually require their own parentheses. Second, in a select, a subquery generally needs to be a scalar subquery. And third, subqueries are generally not allowed as arguments to aggregation functions. Are you sure the construct wasn't select count() . . .?
You can use native SQL.
Here is an example.
String sql = "select {user.*} from User user";
// here creates a hql query from sql
SQLQuery query = session.createSQLQuery(sql);
query.addEntity("user", User.class);
List results = query.list();
//Hibernate modifies the SQL and executes the following command against the database:
select User.id as id0_, User.name as name2_0_ from User user
you can search for Native SQL.
Hope this will help.

Count(*) (asterisk) on Querydsl / MySQL?

The original functional MySQL query that lists all and only the providers that have all the listed tags:
SELECT * FROM provider
INNER JOIN provider_tag
ON provider_tag.provider_id = provider.id AND provider_tag.tag_id in (1, 2)
GROUP BY (provider.id)
HAVING COUNT(*) = 2
Translating to MySQLQuery in Querydsl is straightforward...
MySQLQuery query = new MySQLQuery(conn, dialect);
List<Integer> tagIds = ...;
query.from(provider)
.innerJoin(provider_tag)
.on(providerTag.providerId.eq(provider.id), providerTag.tagId.in(tagIds))
.groupBy(provider.id)
.having(???);
... except for the condition in having.
How do I add COUNT(*) to the query?
EDIT after Timo's 1st correction proposal:
So, the query looks like this:
SearchResults<Tuple> result = query.from(provider)
.innerJoin(providerTag)
.on(providerTag.providerId.eq(provider.id), providerTag.tagId.in(tagIds))
.groupBy(provider.id)
.having(Wildcard.count.eq((long) tagIds.size()))
.listResults(
provider.id,
provider.name);
However, this causes an SQLException Illegal operation on empty result set, if the result set is empty.
My other queries that return an empty result set do not cause exceptions, so I guess I should not need to catch the exception, but there is a problem that should be fixed?
The generated MySQL works perfectly (returns 0 rows), so the problem is not there.
EDIT 2:
The problem was in groupBy(). This seems to work, if one applies the correction shown in the issue.
The querydsl equivalent for COUNT(*) is Wildcard.count.

Categories

Resources