DeltaSpikeデータモジュールのガイド
1. 概要
Apache DeltaSpikeは、Javaプロジェクトにcollection of CDI extensionsを提供するプロジェクトです。実行時にCDI実装を使用できるようにする必要があります。
Of course, it can work with the different implementation of CDI – JBossWeldまたはOpenWebBeans。 また、多くのアプリケーションサーバーでテストされています。
このチュートリアルでは、one of the best known and useful – Data moduleに焦点を当てます。
2. DeltaSpikeデータモジュールのセットアップ
Apache DeltaSpikeデータモジュールはsimplify implementation of the repository patternに使用されます。 reducing a boilerplate code by providing centralized logic for queries creation and executionを許可します。
Spring Dataプロジェクトと非常によく似ています。 データベースをクエリするには、定義された命名規則に従うか、@Queryアノテーションを含むメソッド宣言(実装なし)を定義する必要があります。 実装はCDI拡張機能によって行われます。
次のサブセクションでは、アプリケーションでApache DeltaSpikeDataモジュールをセットアップする方法について説明します。
2.1. 必要な依存関係
アプリケーションでApache DeltaSpike Dataモジュールを使用するには、必要な依存関係をセットアップする必要があります。
Mavenがビルドツールである場合、以下を使用する必要があります。
org.apache.deltaspike.modules
deltaspike-data-module-api
1.8.2
compile
org.apache.deltaspike.modules
deltaspike-data-module-impl
1.8.2
runtime
Gradleを使用している場合:
runtime 'org.apache.deltaspike.modules:deltaspike-data-module-impl'
compile 'org.apache.deltaspike.modules:deltaspike-data-module-api'
Apache DeltaSpike Dataモジュールのアーティファクトは、Maven Centralで利用できます。
run an application with Data module, we also need a JPA and CDI implementations available at runtimeへ。
JavaSEアプリケーションでApacheDeltaSpikeを実行することは可能ですが、ほとんどの場合、アプリケーションサーバー(WildflyやWebSphereなど)にデプロイされます。
アプリケーションサーバーはJavaEEを完全にサポートしているため、これ以上何もする必要はありません。 Java SEアプリケーションの場合、これらの実装を提供する必要があります(たとえば、HibernateおよびJBoss Weldに依存関係を追加することにより)。
次に、EntityManagerに必要な構成についても説明します。
2.2. エンティティマネージャーの構成
Data module requires EntityManager to be injected over CDI。
CDIプロデューサーを使用してこれを実現できます。
public class EntityManagerProducer {
@PersistenceContext(unitName = "primary")
private EntityManager entityManager;
@ApplicationScoped
@Produces
public EntityManager getEntityManager() {
return entityManager;
}
}
上記のコードは、persistence.xmlファイルにprimaryという名前の永続性ユニットが定義されていることを前提としています。
定義の例として以下を見てみましょう。
java:jboss/datasources/example-jee7-seedDS
この例の永続性ユニットはJTAトランザクションタイプを使用します。つまり、使用するトランザクション戦略を提供する必要があります。
2.3. 取引戦略
In case we’re using JTA transaction type for our data source then we have to define Transaction Strategy that will be used in the Apache DeltaSpike repositories。 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データモジュールany abstract class or interface can become a repositoryクラスを使用している場合。
All we have to do is toadd an @Repositoryannotation は、リポジトリが処理する必要のあるJPAエンティティを定義するforEntity属性を持ちます。
@Entity
public class User {
// ...
}
@Repository(forEntity = User.class)
public interface SimpleUserRepository {
// ...
}
または抽象クラスの場合:
@Repository(forEntity = User.class)
public abstract class SimpleUserRepository {
// ...
}
データモジュールは、そのようなアノテーションを持つクラス(またはインターフェイス)を検出し、内部にあるメソッドを処理します。
実行するクエリを定義する可能性はほとんどありません。 次のセクションでは、1つずつ簡単に説明します。
4. メソッド名からのクエリ
define a query is to use method name which follows a defined naming conventionへの最初の可能性。
以下のようになります。
(Entity|Optional|List|Stream) (prefix)(Property[Comparator]){Operator Property [Comparator]}
次に、この定義の各部分に焦点を当てます。
4.1. 戻りタイプ
return type mainly defines how many objects our query might return。 クエリが複数の結果を返す場合に備えて、単一のエンティティタイプを戻り値として定義することはできません。
次のメソッドは、指定された名前のUserが複数ある場合に、例外をスローします。
public abstract User findByFirstName(String firstName);
逆は当てはまりません。結果が単一のエンティティであっても、戻り値をCollectionとして定義できます。
public abstract Collection findAnyByFirstName(String firstName);
戻り値をCollectionとして定義する場合、戻り値の型として1つの値(たとえば、findAny)を提案するメソッド名プレフィックスは抑制されます。
上記のクエリは、メソッド名のプレフィックスが何か別のものを示唆している場合でも、名が一致するすべてのUsersを返します。
このような組み合わせ(Collectionの戻り値の型と単一の値の戻り値を示すプレフィックス)は、コードが直感的で理解しにくくなるため、避ける必要があります。
次のセクションでは、メソッド名のプレフィックスの詳細を示します。
4.2. クエリメソッドのプレフィックス
Prefix defines the action we want to execute on the repository。 最も有用な方法は、指定された検索条件に一致するエンティティを見つけることです。
このアクションには、findBy、findAny、findAll. などの多くのプレフィックスがあります。詳細なリストについては、公式のApache DeltaSpikedocumentationを確認してください。
public abstract User findAnyByLastName(String lastName);
ただし、other method templates which are used for counting and removing entitiesもあります。 テーブル内のすべての行をcountすることができます。
public abstract int count();
また、リポジトリに追加できるremoveメソッドテンプレートが存在します。
public abstract void remove(User user);
countByおよびremoveByメソッドプレフィックスのサポートは、Apache DeltaSpike1.9.0の次のバージョンで追加される予定です。
次のセクションでは、クエリにさらに属性を追加する方法を示します。
4.3. 多くのプロパティを持つクエリ
クエリでは、many properties combined with and operatorsを使用できます。
public abstract Collection findByFirstNameAndLastName(
String firstName, String lastName);
public abstract Collection findByFirstNameOrLastName(
String firstName, String lastName);
必要な数のプロパティを組み合わせることができます。 ネストされたプロパティの検索も利用できます。これについては次に説明します。
4.4. ネストされたプロパティを使用したクエリ
query can also use nested properties。
次の例では、UserエンティティにはタイプAddressのアドレスプロパティがあり、Addressエンティティにはcityプロパティがあります。
@Entity
public class Address {
private String city;
// ...
}
@Entity
public class User {
@OneToOne
private Address address;
// ...
}
public abstract Collection findByAddress_city(String city);
4.5. クエリでの順序
DeltaSpikeを使用すると、define an order in which result should be returnedを実行できます。 昇順と降順の両方を定義できます。
public abstract List findAllOrderByFirstNameAsc();
上に示したように、すべてのwe have to do is to add a part to the method name which contains property name we want to sort by and the short name for the order direction。
多くの注文を簡単に組み合わせることができます。
public abstract List findAllOrderByFirstNameAscLastNameDesc();
次に、クエリ結果のサイズを制限する方法を示します。
4.6. クエリ結果のサイズとページ付けを制限する
結果全体から最初の行をほとんど取得したくない場合があります。 これはいわゆるクエリ制限です。 データモジュールでも簡単です。
public abstract Collection findTop2OrderByFirstNameAsc();
public abstract Collection findFirst2OrderByFirstNameAsc();
Firstとtopは同じ意味で使用できます。
次に、enable query pagination by providing two additional parameters: @FirstResult and @MaxResultを実行できます。
public abstract Collection findAllOrderByFirstNameAsc(@FirstResult int start, @MaxResults int size);
リポジトリにはすでに多くのメソッドが定義されています。 それらの一部は汎用であり、一度定義して各リポジトリで使用する必要があります。
Apache DeltaSpikeには、すぐに使用できる多くのメソッドを持つために使用できる基本タイプがほとんどありません。
次のセクションでは、これを行う方法に焦点を当てます。
5. 基本的なリポジトリタイプ
get some basic repository methods, our repository should extend basic type provided by Apache DeltaSpikeへ。 EntityRepository、FullEntityRepository,などのようなものがいくつかあります。
@Repository
public interface UserRepository
extends FullEntityRepository {
// ...
}
または、抽象クラスを使用します。
@Repository
public abstract class UserRepository extends AbstractEntityRepository {
// ...
}
上記の実装は、追加のコード行を記述することなく多くのメソッドを提供します。そのため、必要なものが得られました。定型コードを大幅に削減しました。
基本リポジトリタイプを使用している場合、追加のforEntity属性値を@Repositoryアノテーション.に渡す必要はありません。
リポジトリのインターフェースの代わりに抽象クラスを使用している場合、カスタムクエリを作成する追加の可能性があります。
Abstract base repository classes, e.g., AbstractEntityRepository gives us an access to fields (via getters) or utility methods which we can use to create a query:
public List findByFirstName(String firstName) {
return typedQuery("select u from User u where u.firstName = ?1")
.setParameter(1, firstName)
.getResultList();
}
上記の例では、typedQueryユーティリティメソッドを使用してカスタム実装を作成しました。
クエリを作成する最後の可能性は、次に示す@Queryアノテーションを使用することです。
6. @Query注釈
SQLquery to execute can also be defined with the @Query annotation。 これは、Springソリューションと非常によく似ています。 値としてSQLクエリを使用してメソッドに注釈を追加する必要があります。
デフォルトでは、これはJPQLクエリです。
@Query("select u from User u where u.firstName = ?1")
public abstract Collection findUsersWithFirstName(String firstName);
上記の例のように、インデックスを介してクエリにパラメータを簡単に渡すことができます。
JPQLではなくネイティブSQLを介してクエリを渡したい場合は、追加のクエリ属性–isNativeを真の値で定義する必要があります。
@Query(value = "select * from User where firstName = ?1", isNative = true)
public abstract Collection findUsersWithFirstNameNative(String firstName);
7. 結論
この記事では、Apache DeltaSpikeの基本的な定義を取り上げ、エキサイティングな部分であるデータモジュールに注目しました。 これは、Spring DataProjectと非常によく似ています。
リポジトリパターンを実装する方法を検討しました。 また、実行するクエリを定義する方法を3つ紹介しました。
いつものように、この記事で使用されている完全なコード例は、over on Githubで入手できます。