送信ゲートウェイ
JPA 受信チャネルアダプターを使用すると、データベースをポーリングして 1 つ以上の JPA エンティティを取得できます。取得したデータは、取得したデータをメッセージペイロードとして使用する Spring Integration フローの開始に使用されます。
さらに、フローの最後で JPA 送信チャネルアダプターを使用してデータを永続化し、本質的に永続化操作の最後でフローを停止することができます。
ただし、フローの途中で JPA 永続化操作を実行するにはどうすればよいですか? 例: Spring Integration メッセージフローで処理しているビジネスデータがあり、それを保持したいが、さらに下流で他のコンポーネントを使用する必要がある場合があります。または、ポーラーを使用してデータベースをポーリングする代わりに、JPQL クエリを実行し、データをアクティブに取得する必要があります。その後、データはフロー内の後続のコンポーネントで処理されます。
これが、JPA 送信ゲートウェイの出番です。データを取得するだけでなく、データを永続化する機能を提供します。これらの使用を容易にするために、Spring Integration は 2 種類の JPA 送信ゲートウェイを提供します。
送信ゲートウェイの更新
送信ゲートウェイの取得
送信ゲートウェイを使用して、データベース内の一部のレコードを保存、更新、削除するアクションを実行する場合は常に、更新する送信ゲートウェイを使用する必要があります。たとえば、entity を使用して永続化する場合、結果としてマージおよび永続化されたエンティティが返されます。その他の場合、影響を受ける(更新または削除された)レコードの数が代わりに返されます。
データベースからデータを取得(選択)するときは、取得送信ゲートウェイを使用します。送信ゲートウェイを取得すると、JPQL、名前付きクエリ(ネイティブまたは JPQL ベース)、またはネイティブクエリ(SQL)を使用してデータを選択し、結果を取得できます。
更新送信ゲートウェイは、JPA 操作の実行後に結果をゲートウェイの応答チャネルに送信することを除いて、関数には送信チャネルアダプターに似ています。
送信ゲートウェイの取得は、受信チャネルアダプターに似ています。
| 一般的な概念のほとんどはそこで説明されているため、最初にこの章で前述した送信チャネルアダプターセクションと受信チャネルアダプターセクションを読むことをお勧めします。 |
この類似性は、共通の機能を可能な限り統合するために主要な JpaExecutor クラスを使用する主な要因でした。
すべての JPA 送信ゲートウェイに共通であり、outbound-channel-adapter と同様、さまざまな JPA 操作の実行に使用できます。
エンティティクラス
JPA クエリ言語 (JPQL)
ネイティブクエリ
名前付きクエリ
構成例については、JPA 送信ゲートウェイのサンプルを参照してください。
共通の構成パラメーター
JPA Outbound Gateways always have access to the Spring Integration Message as input. Consequently, the following parameters are available:
parameter-source-factoryo.s.i.jpa.support.parametersource.ParameterSourceのインスタンスを取得するために使用されるo.s.i.jpa.support.parametersource.ParameterSourceFactoryのインスタンス。ParameterSourceは、クエリで提供されるパラメーターの値を解決するために使用されます。JPA エンティティを使用して操作を実行する場合、parameter-source-factory属性は無視されます。parameterサブエレメントはparameter-source-factoryと相互に排他的であり、提供されたParameterSourceFactoryで構成する必要があります。オプション。use-payload-as-parameter-sourcetrueに設定すると、Messageのペイロードがパラメーターのソースとして使用されます。falseに設定されている場合、Message全体がパラメーターのソースとして使用可能です。JPA パラメーターが渡されない場合、このプロパティはデフォルトでtrueになります。つまり、デフォルトのBeanPropertyParameterSourceFactoryを使用すると、ペイロードの Bean プロパティが JPA クエリのパラメーター値のソースとして使用されます。ただし、JPA パラメーターが渡された場合、このプロパティはデフォルトでfalseに評価されます。その理由は、JPA パラメーターを使用すると SpEL 式を提供できるからです。ヘッダーを含むMessage全体にアクセスできることは非常に有益です。オプション。
送信ゲートウェイの更新
次のリストは、updateing-outbound-gateway に設定できるすべての属性を示し、主要な属性について説明しています。
<int-jpa:updating-outbound-gateway request-channel="" (1)
auto-startup="true"
entity-class=""
entity-manager=""
entity-manager-factory=""
id=""
jpa-operations=""
jpa-query=""
named-query=""
native-query=""
order=""
parameter-source-factory=""
persist-mode="MERGE"
reply-channel="" (2)
reply-timeout="" (3)
use-payload-as-parameter-source="true">
<int:poller/>
<int-jpa:transactional/>
<int-jpa:parameter name="" type="" value=""/>
<int-jpa:parameter name="" expression=""/>
</int-jpa:updating-outbound-gateway>| 1 | 送信ゲートウェイが目的の操作を実行するためのメッセージを受信するチャネル。この属性は、outbound-channel-adapter の channel 属性に似ています。オプション。 |
| 2 | The channel to which the gateway sends the response after performing the required JPA operation. If this attribute is not defined, the request message must have a replyChannel header. Optional. |
| 3 | ゲートウェイが結果を応答チャネルに送信するまで待機する時間を指定します。応答チャネル自体が送信操作をブロックする可能性がある場合にのみ適用されます (たとえば、現在いっぱいである制限された QueueChannel )。値はミリ秒単位で指定します。オプション。 |
残りの属性については、この章で前述しています。構成パラメーターのリファレンスおよび構成パラメーターのリファレンスを参照してください。
Java 構成を使用した構成
次の Spring Boot アプリケーションは、Java で送信アダプターを構成する方法の例を示しています。
@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
@IntegrationComponentScan
public class JpaJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(JpaJavaApplication.class)
.web(false)
.run(args);
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@MessagingGateway
interface JpaGateway {
@Gateway(requestChannel = "jpaUpdateChannel")
@Transactional
void updateStudent(StudentDomain payload);
}
@Bean
@ServiceActivator(channel = "jpaUpdateChannel")
public MessageHandler jpaOutbound() {
JpaOutboundGateway adapter =
new JpaOutboundGateway(new JpaExecutor(this.entityManagerFactory));
adapter.setOutputChannelName("updateResults");
return adapter;
}
}Java DSL を使用した構成
次の Spring Boot アプリケーションは、Java DSL を使用して送信アダプターを構成する方法の例を示しています。
@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
public class JpaJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(JpaJavaApplication.class)
.web(false)
.run(args);
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@Bean
public IntegrationFlow updatingGatewayFlow() {
return f -> f
.handle(Jpa.updatingGateway(this.entityManagerFactory),
e -> e.transactional(true))
.channel(c -> c.queue("updateResults"));
}
}送信ゲートウェイの取得
次の例は、取得する送信ゲートウェイを構成する方法を示しています。
Java DSL
Kotlin DSL
Java
XML
@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
public class JpaJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(JpaJavaApplication.class)
.web(false)
.run(args);
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@Bean
public IntegrationFlow retrievingGatewayFlow() {
return f -> f
.handle(Jpa.retrievingGateway(this.entityManagerFactory)
.jpaQuery("from Student s where s.id = :id")
.expectSingleResult(true)
.parameterExpression("id", "payload"))
.channel(c -> c.queue("retrieveResults"));
}
}
@Bean
fun retrievingGatewayFlow() =
integrationFlow {
handle(Jpa.retrievingGateway(this.entityManagerFactory)
.jpaQuery("from Student s where s.id = :id")
.expectSingleResult(true)
.parameterExpression("id", "payload"))
channel { queue("retrieveResults") }
}
@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
public class JpaJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(JpaJavaApplication.class)
.web(false)
.run(args);
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@Bean
public JpaExecutor jpaExecutor() {
JpaExecutor executor = new JpaExecutor(this.entityManagerFactory);
jpaExecutor.setJpaQuery("from Student s where s.id = :id");
executor.setJpaParameters(Collections.singletonList(new JpaParameter("id", null, "payload")));
jpaExecutor.setExpectSingleResult(true);
return executor;
}
@Bean
@ServiceActivator(channel = "jpaRetrievingChannel")
public MessageHandler jpaOutbound() {
JpaOutboundGateway adapter = new JpaOutboundGateway(jpaExecutor());
adapter.setOutputChannelName("retrieveResults");
adapter.setGatewayType(OutboundGatewayType.RETRIEVING);
return adapter;
}
}
<int-jpa:retrieving-outbound-gateway request-channel=""
auto-startup="true"
delete-after-poll="false"
delete-in-batch="false"
entity-class=""
id-expression="" (1)
entity-manager=""
entity-manager-factory=""
expect-single-result="false" (2)
id=""
jpa-operations=""
jpa-query=""
max-results="" (3)
max-results-expression="" (4)
first-result="" (5)
first-result-expression="" (6)
named-query=""
native-query=""
order=""
parameter-source-factory=""
reply-channel=""
reply-timeout=""
use-payload-as-parameter-source="true">
<int:poller></int:poller>
<int-jpa:transactional/>
<int-jpa:parameter name="" type="" value=""/>
<int-jpa:parameter name="" expression=""/>
</int-jpa:retrieving-outbound-gateway>
| 1 | (Spring Integration 4.0 以降)評価コンテキストのルートオブジェクトとしての requestMessage に対する EntityManager.find(Class entityClass, Object primaryKey) メソッドの primaryKey 値を決定する SpEL 式。entityClass 引数は、存在する場合、entity-class 属性から決定されます。それ以外の場合は、payload クラスから決定されます。id-expression を使用する場合、他のすべての属性は許可されません。オプション。 |
| 2 | A boolean flag indicating whether the select operation is expected to return a single result or a List of results. If this flag is set to true, a single entity is sent as the payload of the message. If multiple entities are returned, an exception is thrown. If false, the List of entities sent as the payload of the message. It defaults to false. Optional. |
| 3 | This non-zero, non-negative integer value tells the adapter not to select more than the specified number of rows on execution of the select operation. By default, if this attribute is not set, all the possible records are selected by a given query. This attribute is mutually exclusive with max-results-expression. Optional. |
| 4 | 結果セット内の結果の最大数を見つけるために使用できる式。max-results と相互に排他的です。オプション。 |
| 5 | この非ゼロ、非負の整数値は、結果を取得する最初のレコードをアダプターに伝えます。この属性は first-result-expression と相互に排他的です。バージョン 3.0 はこの属性を導入しました。オプション。 |
| 6 | This expression is evaluated against the message to find the position of the first record in the result set. This attribute is mutually exclusive to first-result. Version 3.0 introduced this attribute. Optional. |
取得時にエンティティを削除することを選択し、エンティティのコレクションを取得した場合、既定では、エンティティはエンティティごとに削除されます。これにより、パフォーマンスの問題が発生する可能性があります。 または、属性 JSR 317: Java ™ Persistence 2.0 の章では、4.10 の「一括更新および削除操作」で次のように述べています。 “削除操作は、指定されたクラスとそのサブクラスのエンティティにのみ適用されます。関連するエンティティにはカスケードしません。” 詳細については、JSR 317: Java ™ Persistence 2.0 (英語) を参照してください。 |
バージョン 6.0 以降、クエリによってエンティティが返されない場合、Jpa.retrievingGateway() は空のリスト結果を返します。以前は、requiresReply に応じて、フローを終了するか、例外をスローして null が返されていました。または、以前の動作に戻すには、ゲートウェイの後に filter を追加して、空のリストを除外します。空のリストの処理がダウンストリームロジックの一部であるアプリケーションでは、追加の構成が必要です。空リストの処理オプションについては、スプリッタ廃棄チャネルを参照してください。 |
JPA 送信ゲートウェイのサンプル
このセクションには、送信ゲートウェイの更新と送信ゲートウェイの取得のさまざまな使用例が含まれています。
エンティティクラスを使用して更新する
次の例では、org.springframework.integration.jpa.test.entity.Student エンティティクラスを JPA 定義パラメーターとして使用することにより、送信ゲートウェイの更新が永続化されます。
<int-jpa:updating-outbound-gateway request-channel="entityRequestChannel" (1)
reply-channel="entityResponseChannel" (2)
entity-class="org.springframework.integration.jpa.test.entity.Student"
entity-manager="em"/>| 1 | これは、送信ゲートウェイのリクエストチャネルです。outbound-channel-adapter の channel 属性に似ています。 |
| 2 | これは、ゲートウェイが送信アダプターと異なる場所です。これは、JPA 操作からの応答が受信されるチャネルです。ただし、受信した応答に関心がなく、操作のみを実行する場合は、JPA outbound-channel-adapter を使用するのが適切な選択です。エンティティクラスを使用するこの例では、応答は JPA 操作の結果として作成またはマージされたエンティティオブジェクトです。 |
JPQL を使用した更新
次の例では、Java Persistence Query Language(JPQL)を使用してエンティティを更新します。これは、更新送信ゲートウェイの使用を義務付けています。
<int-jpa:updating-outbound-gateway request-channel="jpaqlRequestChannel"
reply-channel="jpaqlResponseChannel"
jpa-query="update Student s set s.lastName = :lastName where s.rollNumber = :rollNumber" (1)
entity-manager="em">
<int-jpa:parameter name="lastName" expression="payload"/>
<int-jpa:parameter name="rollNumber" expression="headers['rollNumber']"/>
</int-jpa:updating-outbound-gateway>| 1 | ゲートウェイが実行する JPQL クエリ。送信ゲートウェイの更新を使用したため、update および delete JPQL クエリのみが実用的な選択になります。 |
long 値を持つ rollNumber というヘッダーも含む String ペイロードを持つメッセージを送信すると、指定されたロール番号を持つ生徒の姓がメッセージペイロードの値に更新されます。更新ゲートウェイを使用する場合、戻り値は常に整数値であり、JPA QL の実行によって影響を受けるレコードの数を示します。
JPQL を使用したエンティティの取得
次の例では、送信ゲートウェイと JPQL の取得を使用して、データベースから 1 つ以上のエンティティを取得(選択)します。
<int-jpa:retrieving-outbound-gateway request-channel="retrievingGatewayReqChannel"
reply-channel="retrievingGatewayReplyChannel"
jpa-query="select s from Student s where s.firstName = :firstName and s.lastName = :lastName"
entity-manager="em">
<int-jpa:parameter name="firstName" expression="payload"/>
<int-jpa:parameter name="lastName" expression="headers['lastName']"/>
</int-jpa:outbound-gateway>id-expression を使用してエンティティを取得する
次の例では、id-expression で送信ゲートウェイを取得して、データベースから唯一のエンティティを取得(検索)します。primaryKey は id-expression 評価の結果です。entityClass は、メッセージ payload のクラスです。
<int-jpa:retrieving-outbound-gateway
request-channel="retrievingGatewayReqChannel"
reply-channel="retrievingGatewayReplyChannel"
id-expression="payload.id"
entity-manager="em"/>名前付きクエリを使用して更新する
名前付きクエリを使用することは、基本的に JPQL クエリを直接使用することと同じです。違いは、次の例に示すように、代わりに named-query 属性が使用されることです。
<int-jpa:updating-outbound-gateway request-channel="namedQueryRequestChannel"
reply-channel="namedQueryResponseChannel"
named-query="updateStudentByRollNumber"
entity-manager="em">
<int-jpa:parameter name="lastName" expression="payload"/>
<int-jpa:parameter name="rollNumber" expression="headers['rollNumber']"/>
</int-jpa:outbound-gateway>| Spring Integration の JPA アダプターを使用する完全なサンプルアプリケーションはこちらにあります [GitHub] (英語) 。 |