I've tried to read through the QueryDSL docs but I am still very confused. I'm accustomed to writing a lot of SQL, but this is my first real crack at using QueryDSL w/ JPQL (JPA2).
I have the following entity:
@Entity
public class Provider implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Version
@Column(name = "version")
private Integer version;
private String name;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "provider_contact", joinColumns = @JoinColumn(name = "contact_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "provider_id", referencedColumnName = "id"))
@OrderColumn
private Collection<Contact> contact;
}
where Contact is a simple entity with an id
for a pk.
@Entity
public class Contact {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
/**
* User first name
*/
@NotNull
private String firstName;
/**
* User last name
*/
@NotNull
private String lastName;
}
I'm trying to write a query which returns a Contact
object given a specific Contact.id and Provider.id. If the Contact object is not a part of the Provider's Contact collection, I'm looking for a null value.
I've tried the following:
public Contact getContact( long providerId, long contactId ){
Predicate p = QProvider.provider.id.eq(providerId).and(QContact.contact.id.eq(contactId));
JPQLQuery query = new JPAQuery(em);
return query.from(QProvider.provider).innerJoin(QProvider.provider.contact).where(p).singleResult(QContact.contact);
}
but I'm getting the following error:
Caused by: java.lang.IllegalArgumentException: Undeclared path 'contact'. Add this path as a source to the query to be able to reference it.
at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:78)
at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
at com.mysema.query.types.PathImpl.accept(PathImpl.java:94)
I'm presuming it has something to do with the fact that my predicate references QContact.contact direction and not part of the QProvider.provider.contact object, but I'm really at a loss as to figure out how this should be done.
Am I even on the right track? I'm not even sure my join is correct either.
Subqueries To create a subquery you create a JPASubQuery instance, define the query parameters via from, where etc and use unique or list to create a subquery, which is just a type-safe Querydsl expression for the query. unique is used for a unique (single) result and list for a list result.
JPQL provides an additional type of identification variable, a join variable, which represent a more limited iteration over specified collections of objects. In JPQL, JOIN can only appear in a FROM clause. The INNER keyword is optional (i.e. INNER JOIN is equivalent to JOIN).
Querydsl is an extensive Java framework, which allows for the generation of type-safe queries in a syntax similar to SQL. It currently has a wide range of support for various backends through the use of separate modules including JPA, JDO, SQL, Java collections, RDF, Lucene, Hibernate Search, and MongoDB.
The querydsl-apt dependency is an annotation processing tool (APT) — implementation of corresponding Java API that allows processing of annotations in source files before they move on to the compilation stage.
This should work
public Contact getContact(long providerId, long contactId) {
QProvider provider = QProvider.provider;
QContact contact = QContact.contact;
return new JPAQuery(em).from(provider)
.innerJoin(provider.contact, contact)
.where(provider.id.eq(providerId), contact.id.eq(contactId))
.singleResult(contact);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With