Querydsl: @QueryInit not working with deep nested paths

Created on 6 Apr 2017  路  11Comments  路  Source: querydsl/querydsl

I am using QueryDSL 4.1.4 with Spring Data in a project and am having trouble using it with nested paths. Consider the following JPA classes:

@Entity @QueryEntity class Company {}

@Entity
@QueryEntity
class Contract {
  @ManyToOne
  @QueryInit("*.*")
  Company buyer;

  @ManyToOne
  @QueryInit("*.*")
  Company seller;
}

@Entity @QueryEntity class Bill { @ManyToOne @QueryInit("*.*") Contract contract; }

@Entity @QueryEntity class Payment { @ManyToOne @QueryInit("*.*") Bill bill; }

@Entity @QueryEntity class Posting { @ManyToOne @QueryInit("*.*") Payment payment; }

With this set up, the following throws NullPointerException:

QPosting.posting.payment.bill.contract.buyer.name.equalsIgnoreCase(...)

Debugging shows that QPosting.posting.payment.bill.contract.buyer (and QPosting.posting.payment.bill.contract.seller) is null.

The following however work fine:

  1. QPayment.payment.bill.contract.buyer.name.equalsIgnoreCase(...)
  2. QBill.bill.contract.buyer.name.equalsIgnoreCase(...)
  3. QContract.contract.buyer.name.equalsIgnoreCase(...)

I am using com.mysema.maven:apt-maven-plugin:1.1.1 and QueryDSL version 4.1.4.

A full sample project is available here. Run Maven tests as mvn clean test to see the error.

Most helpful comment

I just encountered the same issue in my model.

I get a NullPointerException when calling upisaniPredmet.upisaniElement.upis.student.

upisaniPredmet.upisaniElement is not null.
upisaniPredmet.upisaniElement.upis is not null.
upisaniPredmet.upisaniElement.upis.student is null.

All 11 comments

I just encountered the same issue in my model.

I get a NullPointerException when calling upisaniPredmet.upisaniElement.upis.student.

upisaniPredmet.upisaniElement is not null.
upisaniPredmet.upisaniElement.upis is not null.
upisaniPredmet.upisaniElement.upis.student is null.

I have exactly the same problem. Must be the bug

+1

any solutions? facing it too.

===

Well I'm using version 4.2.1....
I annotate the top level attribute with @QueryInit("*")as the documentation suggests but it fails.
Then I checked the source code , changed it to@QueryInit("*.*") then it works fine.

Maybe I misinterpreted the documentation but it is somehow confusing , I think it would be better to explain *.*works for multi-level queries while *refers to next-level attributes (perhaps?)

Same here, expected this just to work out of the box :(

Please give us the answer,thank you verymuch.

@POJOa Thank you very much :)

Someone managed to resolve the error? I have the same problem.

@lucasfrederico
By default Querydsl initializes only reference properties of the first two levels. In cases where longer initialization paths are required, these have to be annotated in the domain types via com.mysema.query.annotations.QueryInit annotations. QueryInit is used on properties where deep initializations are needed.

http://www.querydsl.com/static/querydsl/3.5.0/reference/html/ch03s03.html#d0e2181

Hey, sorry to bump this old thread but I'm facing the same problem. Is there a fix for this?

There is no fix for this, and it will likely not get fixed because initializing paths so deep is incredibly computationally expensive. As a result, QueryInits from referenced classes are not used transitively, so you have to specify the QueryInits where you want them.

If you want to initialise the path QPosting.posting.payment.bill.contract.buyer you will explicitly have to initialise it, as such:

@Entity @QueryEntity class Posting {
    @ManyToOne @QueryInit("*.*", "bill.contract.buyer") Payment payment;
}

That said, there is one known issue regarding path initialisation, and that one is related to entities that implement Comparable. That issue is described in #2572 and I have suggested a fix in #2573.

Was this page helpful?
0 / 5 - 0 ratings