1概要
Apache DeltaSpike は、Javaプロジェクト用の CDI拡張機能 のコレクションを提供するプロジェクトです。実行時にCDI実装が利用可能であることが必要です。
-
もちろん、CDI ** の異なる実装(JBoss WeldまたはOpenWebBeans)でも機能します。多くのアプリケーションサーバーでもテストされています。
このチュートリアルでは、最もよく知られていて有用なものの1つであるデータモジュールに焦点を当てます。
2 DeltaSpikeデータモジュールセットアップ
Apache DeltaSpike Dataモジュールは、リポジトリパターンの実装を単純化するために使用されます。クエリの作成と実行のための集中型ロジックを提供することで、定型コードを減らすことができます。
これは Spring Data プロジェクトとよく似ています。データベースを問い合わせるには、定義された命名規則に従うか、または @ Query アノテーションを含むメソッド宣言を(実装なしで)定義する必要があります。実装はCDI拡張によって行われます。
次のサブセクションでは、アプリケーションでApache DeltaSpike Dataモジュールを設定する方法について説明します。
2.1. 必要な依存関係
アプリケーションでApache DeltaSpike Dataモジュールを使用するには、必要な依存関係を設定する必要があります。
Mavenが私たちのビルドツールであるとき、私たちは使わなければなりません:
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-api</artifactId>
<version>1.8.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-impl</artifactId>
<version>1.8.2</version>
<scope>runtime</scope>
</dependency>
Gradleを使用している場合
runtime 'org.apache.deltaspike.modules:deltaspike-data-module-impl'
compile 'org.apache.deltaspike.modules:deltaspike-data-module-api'
Apache DeltaSpike Dataモジュール成果物は、Maven Centralで入手できます。
Dataモジュールでアプリケーションを実行するためには、実行時に利用可能なJPAとCDIの実装も必要です。
Java SEアプリケーションでApache DeltaSpikeを実行することは可能ですが、ほとんどの場合、それはApplication Server(WildflyやWebSphereなど)にデプロイされます。
アプリケーションサーバーはJava EEを完全にサポートしているので、これ以上行う必要はありません。 Java SEアプリケーションの場合、これらの実装を提供する必要があります(たとえば、HibernateおよびJBoss Weldに依存関係を追加することによって)。
次に、 EntityManager に必要な設定についても説明します。
2.2. エンティティマネージャの設定
-
DataモジュールはCDI ** の上に EntityManager をインジェクトすることを要求します。
CDIプロデューサーを使用してこれを実現できます。
public class EntityManagerProducer {
@PersistenceContext(unitName = "primary")
private EntityManager entityManager;
@ApplicationScoped
@Produces
public EntityManager getEntityManager() {
return entityManager;
}
}
上記のコードは persistence.xml ファイルで定義された primary という名前の永続化ユニットがあると仮定しています。
定義の例として以下を見てみましょう:
<persistence-unit name="primary" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/baeldung-jee7-seedDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show__sql" value="false"/>
</properties>
</persistence-unit>
この例の永続ユニットはJTAトランザクションタイプを使用しています。これは、使用するトランザクション戦略を提供する必要があることを意味します。
2.3. 取引戦略
-
データソースにJTAトランザクションタイプを使用している場合は、Apache DeltaSpikeリポジトリで使用されるトランザクション戦略を定義する必要があります** 。 apache-deltaspike.properties ファイル内( META-INF ディレクトリの下)で実行できます。
globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy
定義できるトランザクション戦略は4種類あります。
-
BeanManagedUserTransactionStrategy
-
ResourceLocalTransactionStrategy
-
ContainerManagedTransactionStrategy
-
EnvironmentAwareTransactionStrategy
それらはすべて org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy を実装しています。
これが、データモジュールに必要な設定の最後の部分でした。
次に、リポジトリパターンクラスの実装方法を説明します。
3リポジトリクラス
Apache DeltaSpikeデータモジュール を使用している場合は、抽象クラスまたはインタフェースをリポジトリ クラスにすることができます。
-
私たちがしなければならないのは、 リポジトリが扱うべきJPAエンティティを定義する forEntity 属性を持つ @ Repository アノテーション ** を追加することです。
@Entity
public class User {
//...
}
@Repository(forEntity = User.class)
public interface SimpleUserRepository {
//...
}
あるいは抽象クラスでは:
@Repository(forEntity = User.class)
public abstract class SimpleUserRepository {
//...
}
データモジュールはそのようなアノテーションを持つクラス(またはインターフェース)を発見し、それが内部にあるメソッドを処理します。
実行するクエリを定義する可能性はほとんどありません。次のセクションで、1つずつ簡単に説明します。
4メソッド名からの問い合わせ
クエリを定義する最初の方法は、定義された命名規則に従うメソッド名を使うことです。
以下のようになります。
(Entity|Optional<Entity>|List<Entity>|Stream<Entity>) (prefix)(Property[Comparator]){Operator Property[Comparator]}
次に、この定義の各部分に焦点を当てます。
4.1. 返品タイプ
戻り値の型は主に、クエリが返す可能性のあるオブジェクトの数を定義します。クエリが複数の結果を返す可能性がある場合は、単一のエンティティタイプを戻り値として定義することはできません。
次のメソッドは、指定された名前を持つ User が複数ある場合に例外をスローします。
public abstract User findByFirstName(String firstName);
反対のことは当てはまりません。結果が単一のエンティティになる場合でも、戻り値を Collection として定義できます。
public abstract Collection<User> findAnyByFirstName(String firstName);
戻り値を Collection と定義した場合、戻り値の型として1つの値を示唆するメソッド名の接頭辞( findAny など)は抑制されます。
上記のクエリは、たとえメソッド名の接頭辞が異なる何かを示唆していても、名が一致するすべての Users を返します。
そのような組み合わせ( Collection 戻り型と単一の値の戻りを示唆する接頭辞)は、コードが直感的で理解しにくくなるため、避けるべきです。
次のセクションでは、メソッド名の接頭辞について詳しく説明します。
4.2. クエリメソッドのプレフィックス
-
プレフィックスはリポジトリ上で実行したいアクションを定義します** 。最も有用なものは、与えられた検索基準に一致するエンティティを見つけることです。
このアクションには、 findBy 、 findAny 、 __findAllのように多くのプレフィックスがあります。 __詳細なリストについては、公式のApache DeltaSpike 文書 をチェックしてください。
public abstract User findAnyByLastName(String lastName);
ただし、エンティティのカウントと削除に使用される他のメソッドテンプレートもあります。テーブル内のすべての行をカウントすることができます。
public abstract int count();
また、 remove メソッドテンプレートがあり、それをリポジトリに追加できます。
public abstract void remove(User user);
countBy および removeBy メソッドプレフィックスのサポートは、Apache DeltaSpike 1.9.0の次のバージョンで追加される予定です。
次のセクションでは、クエリにさらに属性を追加する方法を示します。
4.3. 多くのプロパティを使用したクエリ
クエリでは、 and 演算子 と組み合わせて 多数のプロパティを使用できます。
public abstract Collection<User> findByFirstNameAndLastName(
String firstName, String lastName);
public abstract Collection<User> findByFirstNameOrLastName(
String firstName, String lastName);
必要なだけプロパティを組み合わせることができます。入れ子になったプロパティの検索も可能です。
4.4. 入れ子になったプロパティでクエリ
-
クエリは入れ子のプロパティ** も使用できます。
次の例では、 User entityは Address 型のaddressプロパティを持ち、 Address entityは city プロパティを持ちます。
@Entity
public class Address {
private String city;
//...
}
@Entity
public class User {
@OneToOne
private Address address;
//...
}
public abstract Collection<User> findByAddress__city(String city);
4.5. クエリ内の順序
DeltaSpikeでは、結果が返される順序を定義することができます。昇順と降順の両方を定義できます。
public abstract List<User> findAllOrderByFirstNameAsc();
上に示したように、** 私たちがしなければならないのは、ソートしたいプロパティ名と順序方向の短い名前を含む部分をメソッド名に追加することです。
多くの注文を簡単に組み合わせることができます。
public abstract List<User> findAllOrderByFirstNameAscLastNameDesc();
次に、クエリ結果のサイズを制限する方法を説明します。
4.6. クエリ結果のサイズとページ区切りを制限する
結果全体から最初の数行を取得したい場合は、ユースケースがあります。いわゆるクエリ制限です。データモジュールでも簡単です。
public abstract Collection<User> findTop2OrderByFirstNameAsc();
public abstract Collection<User> findFirst2OrderByFirstNameAsc();
First と top は同じ意味で使用できます。
-
@ FirstResult と @ MaxResult__の2つの追加パラメータを指定することで、クエリのページ区切りを有効にすることができます。
public abstract Collection<User> findAllOrderByFirstNameAsc(@FirstResult int start, @MaxResults int size);
リポジトリにはすでにたくさんのメソッドが定義されています。それらのいくつかは一般的なものであり、一度定義して各リポジトリで使用するべきです。
Apache DeltaSpikeには、箱から出してたくさんのメソッドを用意するために使用できる基本的なタイプがいくつか用意されています。
次のセクションでは、これを行う方法に焦点を当てます。
5基本リポジトリタイプ
-
いくつかの基本的なリポジトリメソッドを取得するために、私たちのリポジトリはApache DeltaSpike ** によって提供される基本的な型を拡張するべきです。 EntityRepository 、 FullEntityRepository、 などのようなものがあります。
@Repository
public interface UserRepository
extends FullEntityRepository<User, Long> {
//...
}
あるいは抽象クラスを使う:
@Repository
public abstract class UserRepository extends AbstractEntityRepository<User, Long> {
//...
}
上記の実装は、追加のコード行を記述することなく多くのメソッドを提供するので、必要なものを入手できました - 定型コードを大幅に削減します。
ベースリポジトリタイプを使用している場合は、追加の forEntity 属性値を @ Repository アノテーション __. __に渡す必要はありません。
リポジトリにインタフェースの代わりに抽象クラスを使用している場合は、カスタムクエリを作成する可能性があります。
-
抽象ベースリポジトリクラス、例えば AbstractEntityRepository は、クエリを作成するために使用できるフィールドまたはユーティリティメソッドへのアクセスを提供します。
public List<User> findByFirstName(String firstName) {
return typedQuery("select u from User u where u.firstName = ?1")
.setParameter(1, firstName)
.getResultList();
}
上記の例では、 typedQuery ユーティリティメソッドを使用してカスタム実装を作成しました。
クエリを作成する最後の可能性は、次に示す @ Query アノテーションを使用することです。
6. @クエリ 注釈
実行するSQL クエリは @ Query アノテーション で定義することもできます。これはSpringソリューションと非常によく似ています。値としてSQLクエリを使用してメソッドに注釈を追加する必要があります。
デフォルトではこれはJPQLクエリです。
@Query("select u from User u where u.firstName = ?1")
public abstract Collection<User> findUsersWithFirstName(String firstName);
上記の例のように、インデックスを介してクエリにパラメータを簡単に渡すことができます。
JPQLではなくネイティブSQLを介してクエリを渡したい場合は、追加のクエリ属性 - 真の値を持つ isNative を定義する必要があります。
@Query(value = "select ** from User where firstName = ?1", isNative = true)
public abstract Collection<User> findUsersWithFirstNameNative(String firstName);
7. 結論
この記事では、Apache DeltaSpikeの基本的な定義を取り上げ、刺激的な部分であるデータモジュールに焦点を当てました。 Spring Data Projectと非常によく似ています。
リポジトリパターンの実装方法を調べました。また、実行するクエリを定義する方法を3つ紹介しました。
いつものように、この記事で使用されている完全なコード例はhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/deltaspike[Githubでさらに入手]です。