Spring Data JPA giving error when joining over multiple tables - spring-boot

I have the following query which joins over multiple tables for getting the necessary output:
public interface UserRepositoryJpaRepository <User, Long> {
#Query("SELECT o.id, u.id, u.name, i.name,i.id FROM User u, Item i LEFT JOIN u.order o LEFT JOIN o.payment p WHERE p.id=:id AND o.id=i.order")
List<MixedResult>getUsersWithOrderByPayment_id(#Param("id") Long id);
However, when running Spring Boot 1.4.1 with Spring Data JPA 1.10.5.BUILD-SNAPSHOT, I am getting the following error message :
org.springframework.dao.InvalidDataAccessApiUsageException: No aliases
found in result tuple! Make sure your query defines aliases!; nested
exception is java.lang.IllegalStateException: No aliases found in
result tuple! Make sure your query defines aliases!
However, I see that the generated SQL is fine and it works

Related

Spring data jpa projection could not extract ResultSet

I'm trying to map my entity to projection using the below query but i'm getting error as
Exception : could not extract ResultSet SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
here is the query
#Query("select rf.rfqID as rfqID,rf.creationDate as creationDate," +
"rf.deadLineDate as deadLineDate,rf.details as details," +
"rf.message as message, rf.rfqDoc as rfqDoc," +
"CASE WHEN (rf.creationDate > CURRENT_DATE) THEN 'open' ELSE 'closed' END as status," +
"rf.rfqMembers as rfqMembers " +
"from RFQ rf where rf.createdBy = ?1")
Page<RfqDto> loadAllRfq(String creator, Pageable pageable);
In my Dto I have an extra status column which I don't want to persist in db and would like to get the status via query
here is my projection interface
public interface RfqDto {
String rfqID();
Date creationDate();
Date deadLineDate();
String details();
String message();
String rfqDoc();
String status();
List<RfqMember> rfqMembers();
}
The root cause of your problem is here:
In my Dto I have an extra status column which I don't want to persist in db and would like to get the status via query
As it's explained in the documentation:
The important bit here is that the properties defined here exactly match properties in the aggregate root.
...
The query execution engine creates proxy instances of that interface at runtime for each element returned and forwards calls to the exposed methods to the target object.
So, you can not use spring data jpa projection for your case. You can not use hibernate/jpa projection as well, because it dose not support collections in row results.
You can try to use Blaze-Persistence Entity Views. See for example this answer.

How to use #QueryInit to init path to attribute of embedded object in QueryDSL query?

According to the QueryDSL docs, (http://www.querydsl.com/static/querydsl/4.0.8/reference/html_single/#d0e2250) only the first two levels of paths are initialized in generated Q classes, so if an object A has a relationship inside a #Entity B defined by an #JoinColumn, you can't do things like b.a.id in a query to access the id for A from inside B. They have a #QueryInit annotation to use in those situations where we need to have deeper paths but the docs are very brief and I don't understand how its used. Right now Im getting an "invalid path" exception when I try to run the query inside my application. Has anyone use #QueryInit to fix a problem similar to mine ?
The query where clause (ie. in QueryDSL) is something like a.id.eq(b.a.id) where a is "embedded" inside b
The exception Im seeing is:
"org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'b.a.id' [select a from A a where a.id is not null and (a.id = b.a.id and a.amount <= sum(b.amount))]; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'b.a.id' [select a from A a where a.id is not null and (a.id = b.a.id and a.amountCents <= sum(b.amountCents))]",
The query Im trying to "translate" into QueryDSL looks like this:
SELECT * FROM A a
WHERE a.amount <= (SELECT SUM(b.amount) FROM B b WHERE b.a_id=a.id);
The predicate ended up simply being:
a.amount.loe(
JPAExpressions.select(b.amount.sum()).from(b).where(a.id.eq(b.a.id)))
)

Using "having" on join clause of Spring JPA specification

I have a repository of Users; each User has a OneToMany relationship with a collection of Posts.
How can I filter (and page) the repository of users by the number of posts they have using JPA specifications?
My initial attempt looked as such:
public static Specification<User> receiptNumberGreaterThanOrEqualTo(int numberToFilterBy) {
return (users, query, cb) -> greaterThanOrEqualTo(cb.count(users.get("posts")), Long.valueOf(numberToFilterBy));
}
This however caused an error to the effect of:
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 ')>=9 limit 100'
This is because the #OneToMany join expects a HAVING clause to be used rather than WHERE, i.e. select * from users outer left join posts on users.id = posts.id having(count(posts) > someNumber) where user.id = "some-id"
vs
select * from users outer left join posts on users.id = posts.id where user.id = "something" and count(posts) > someNumber;
I can generate a query with the having keyword by creating a join between user and posts, and then doing as follows:
query.having(cb.greaterThanOrEqualTo(cb.count(joinOfPosts), Long.valueOf(numberToFilterBy))), but the type of this is CriteriaQuery, and I'm unsure how to turn this into a Specification.
I solved this by using the size() method on the criteriaBuilder,
ie.
(users, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(criteriaBuilder.size(users.get("posts")), numberToFilterBy);

spring data jpa specification join fetch is not working

I am trying to use Spring Data JPA Specificaiton to query data, but I got some problem here.
The Java code is as below:
List<NoticeEntity> studentNoticeEntityList = noticeRepository
.findAll((root, criteriaQuery, criteriaBuilder) -> {
criteriaQuery.distinct(true);
root.fetch(NoticeEntity_.contentEntitySet, JoinType.LEFT);
Predicate restrictions = criteriaBuilder.conjunction();
SetJoin<NoticeEntity, UserNoticeEntity> recipientNoticeJoin = root
.join(NoticeEntity_.recipientNoticeEntitySet, JoinType.INNER);
recipientNoticeJoin.on(criteriaBuilder.equal(
recipientNoticeJoin.get(UserNoticeEntity_.recipientStatus), NoticeRecipientStatus.Unread));
Join<UserNoticeEntity, WeChatUserEntity> recipientUserJoin = recipientNoticeJoin
.join(UserNoticeEntity_.user);
restrictions = criteriaBuilder.and(restrictions,
criteriaBuilder.equal(recipientUserJoin.get(WeChatUserEntity_.id), id));
// recipientNoticeJoin.fetch(UserNoticeEntity_.user, JoinType.INNER);
return restrictions;
});
When I comment the code "recipientNoticeJoin.fetch(UserNoticeEntity_.user, JoinType.INNER);", it is working fine, but when I un-comment this, I will get error:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
So, I am wondering if join fetch is supported by using Specification way, or there is something wrong with my code.
I know there is another way by using #Query("some hql"), but somehow I just prefer to use the Specification way.
Thanks a lot.
The error specifies that you're missing an entity from your select list. Try this:
criteriaQuery.multiselect(root, root.get(NoticeEntity_.recipientNoticeEntitySet);
Also, hibernate may run a count query first to determine the number of results, and this can cause the above error. You can avoid this breaking by checking the return type of the query before adding the fetch.
Eager fetching in a Spring Specification

Inner Join and Group By using Specification in Spring Data JPA

I am trying to fetch the employee details whose empltype is clerk and whose joining date is the recent one.
For which the query looks like following in SQL Server 2008:
select
*
from
employee jj
inner join
(
select
max(join_date) as jdate,
empltype as emptype
from
employee
where
empltype='clerk'
group by empltype
) mm
on jj.join_date=mm.jdate and jj.empltype=mm.emptype;
I am using SpringData JPA as my persistence layer using QuerylDSL,Specification and Predicate to fetch the data.
I am trying to convert the above query either in QueryDSL or Specification, but unable to hook them properly.
Employee Entity :
int seqid;(sequence id)
String empltype:
Date joindate;
String role;
Predicate method in Specifcation Class :
Predicate toPredicate(Root<employee> root,CriteriaQuery <?> query,CriteriaBuilder cb)
{
Predicate pred=null;
// Returning the rows matching the joining date
pred=cb.equal(root<Emplyoee_>.get("joindate"));
//**//
}
What piece of code should be written in //**// to convert about SQL query to JPA predicate. any other Spring Data JPA impl like #Query,NamedQuery or QueryDSL which returns Page also works for me.
Thanks in advance
I wrote this in notepad and it hasn't been tested but I think you're looking for something like
QEmployee e1 = new QEmployee("e1");
QEmployee e2 = new QEmployee("e2");
PathBuilder<Object[]> eAlias = new PathBuilder<Object[]>(Object[].class, "eAlias");
JPASubQuery subQuery = JPASubQuery().from(e2)
.groupBy(e2.empltype)
.where(e2.empltype.eq('clerk'))
.list(e2.join_date.max().as("jdate"), e2.emptype)
jpaQuery.from(e1)
.innerJoin(subQuery, eAlias)
.on(e1.join_date.eq(eAlias.get("jdate")), e1.emptype.eq(eAlias.get("emptype")))
.list(qEmployee);

Resources