web-dev-qa-db-ja.com

QueryDSL / JPQL:結合クエリを作成する方法は?

QueryDSLのドキュメントを読み込もうとしましたが、それでも非常に混乱しています。私は多くのSQLを書くことに慣れていますが、これは、JPQL(JPA2)を使用したQueryDSLの使用に関する私の最初の本当の亀裂です。

私は次のエンティティを持っています:

@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;
}

ここで、Contactは、pkのidを持つ単純なエンティティです。

@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;
}

特定のContact.idとProvider.idを指定してContactオブジェクトを返すクエリを作成しようとしています。 ContactオブジェクトがプロバイダーのContactコレクションの一部ではない場合、null値を探しています。

私は以下を試しました:

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

しかし、次のエラーが発生します。

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)

述語がQProvider.provider.contactオブジェクトの一部ではなくQContact.contact方向を参照しているという事実と関係があると思いますが、これをどのように行うべきかを理解するのに本当に迷っています。

私も正しい方向に進んでいますか?自分の参加が正しいかどうかさえわかりません。

11
Eric B.

これはうまくいくはずです

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);
}
19