1. 概要

Querydslは広範なJavaフレームワークであり、SQLに類似したドメイン固有言語でタイプセーフクエリを作成および実行するのに役立ちます。

この記事では、JavaPersistenceAPIを使用したQuerydslについて説明します。

ここで簡単に言うと、HibernateのHQLはQuerydslの最初のターゲット言語でしたが、現在はJPA、JDO、JDBC、Lucene、Hibernate Search、MongoDB、Collections、RDFBeanをバックエンドとしてサポートしています。

2. 準備

まず、必要な依存関係をMavenプロジェクトに追加しましょう。

<properties>
    <querydsl.version>2.5.0</querydsl.version>
</properties>

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>${querydsl.version}</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>${querydsl.version}</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.1</version>
</dependency>

それでは、MavenAPTプラグインを構成しましょう。

<project>
    <build>
    <plugins>
    ...
    <plugin>
        <groupId>com.mysema.maven</groupId>
        <artifactId>apt-maven-plugin</artifactId>
        <version>1.1.3</version>
        <executions>
        <execution>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>target/generated-sources</outputDirectory>
                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
        </execution>
        </executions>
    </plugin>
    ...
    </plugins>
    </build>
</project>

JPAAnnotationProcessor は、 javax.persistence.Entity アノテーションが付けられたドメインタイプを検索し、それらのクエリタイプを生成します。

3. Querydslを使用したクエリ

クエリは、ドメインタイプのプロパティを反映する生成されたクエリタイプに基づいて構築されます。 また、関数/メソッドの呼び出しは、完全にタイプセーフな方法で構築されます。

クエリパスと操作はすべての実装で同じであり、Queryインターフェイスにも共通のベースインターフェイスがあります。

3.1. エンティティとQuerydslクエリタイプ

まず、例を見ていくときに使用する単純なエンティティを定義しましょう。

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String firstname;

    @Column
    private String surname;
    
    Person() {
    }

    public Person(String firstname, String surname) {
        this.firstname = firstname;
        this.surname = surname;
    }

    // standard getters and setters

}

Querydslは、QPersonという単純な名前のクエリタイプをPersonと同じパッケージに生成します。 QPerson は、 Person タイプの代表として、Querydslクエリで静的に型付けされた変数として使用できます。

最初– QPerson には、静的フィールドとしてアクセスできるデフォルトのインスタンス変数があります。

QPerson person = QPerson.person;

または、次のように独自のPerson変数を定義することもできます。

QPerson person = new QPerson("Erich", "Gamma");

3.2. JPAQueryを使用してクエリを作成する

これで、クエリにJPAQueryインスタンスを使用できます。

JPAQuery query = new JPAQuery(entityManager);

entityManagerはJPAEntityManagerであることに注意してください。

ここで、簡単な例として、「Kent」という名のすべての人物を取得してみましょう。

QPerson person = QPerson.person;
List<Person> persons = query.from(person).where(person.firstName.eq("Kent")).list(person);

from 呼び出しはクエリのソースとプロジェクションを定義し、 where 部分はフィルターを定義し、listはQuerydslに一致するすべての要素を返すように指示します。

複数のフィルターを使用することもできます。

query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));

または:

query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));

ネイティブJPQL形式では、クエリは次のように記述されます。

select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"

「または」を使用してフィルターを組み合わせる場合は、次のパターンを使用します。

query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));

4. Querydslでの順序付けと集約

次に、Querydslライブラリ内で順序付けと集計がどのように機能するかを見てみましょう。

4.1. 注文

結果をsurnameフィールドの降順で並べ替えることから始めます。

QPerson person = QPerson.person;
List<Person> persons = query.from(person)
    .where(person.firstname.eq(firstname))
    .orderBy(person.surname.desc())
    .list(person);

4.2. 集約

利用可能なものがいくつかあるので(合計、平均、最大、最小)、単純な集計を使用してみましょう。

QPerson person = QPerson.person;    
int maxAge = query.from(person).list(person.age.max()).get(0);

4.3. GroupByを使用した集約

com.mysema.query.group.GroupBy クラスは、メモリ内のクエリ結果を集約するために使用できる集約機能を提供します。

結果がMapとして返され、 firstname がキーで、 maxageが値として返される簡単な例を次に示します。

QPerson person = QPerson.person;   
Map<String, Integer> results = 
  query.from(person).transform(
      GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));

5. Querydslを使用したテスト

次に、Querydslを使用してDAO実装を定義し、次の検索操作を定義しましょう。

public List<Person> findPersonsByFirstnameQuerydsl(String firstname) {
    JPAQuery query = new JPAQuery(em);
    QPerson person = QPerson.person;
    return query.from(person).where(person.firstname.eq(firstname)).list(person);
}

次に、この新しいDAOを使用していくつかのテストを作成し、Querydslを使用して、新しく作成された Person オブジェクト( Person Dao クラスで実装)と別のテスト集計を検索します。 GroupByクラスの使用がテストされます。

@Autowired
private PersonDao personDao;

@Test
public void givenExistingPersons_whenFindingPersonByFirstName_thenFound() {
    personDao.save(new Person("Erich", "Gamma"));
    Person person = new Person("Kent", "Beck");
    personDao.save(person);
    personDao.save(new Person("Ralph", "Johnson"));

    Person personFromDb =  personDao.findPersonsByFirstnameQuerydsl("Kent").get(0);
    Assert.assertEquals(person.getId(), personFromDb.getId());
}

@Test
public void givenExistingPersons_whenFindingMaxAgeByName_thenFound() {
    personDao.save(new Person("Kent", "Gamma", 20));
    personDao.save(new Person("Ralph", "Johnson", 35));
    personDao.save(new Person("Kent", "Zivago", 30));

    Map<String, Integer> maxAge = personDao.findMaxAgeByName();
    Assert.assertTrue(maxAge.size() == 2);
    Assert.assertSame(35, maxAge.get("Ralph"));
    Assert.assertSame(30, maxAge.get("Kent"));
}

6. 結論

このチュートリアルでは、Querydslを使用してJPAプロジェクトをビルドする方法を説明しました。

この記事の完全な実装は、githubプロジェクトにあります。これはEclipseベースのMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。

ここでの簡単な注意は、単純なmavenビルド(mvn clean install)を実行して、タイプを target /generated-sources に生成します。次に、Eclipseを使用している場合は、フォルダーをソースフォルダーとして含めます。プロジェクトの。