46.16. 本文とヘッダーをテキストとして保存する
JdbcAggregationRepository を設定して、メッセージ本文と select (ed) ヘッダーを文字列として別々の列に格納できます。たとえば、本文を保存するには、次の 2 つのヘッダー companyName と accountName は次の SQL を使用します。
CREATE TABLE aggregationRepo3 (
id varchar(255) NOT NULL,
exchange blob NOT NULL,
version BIGINT NOT NULL,
body varchar(1000),
companyName varchar(1000),
accountName varchar(1000),
constraint aggregationRepo3_pk PRIMARY KEY (id)
);
CREATE TABLE aggregationRepo3_completed (
id varchar(255) NOT NULL,
exchange blob NOT NULL,
version BIGINT NOT NULL,
body varchar(1000),
companyName varchar(1000),
accountName varchar(1000),
constraint aggregationRepo3_completed_pk PRIMARY KEY (id)
);
次に、以下に示すように、この動作を有効にするようにリポジトリーを設定します。
<bean id="repo3"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
<property name="repositoryName" value="aggregationRepo3"/>
<property name="transactionManager" ref="txManager3"/>
<property name="dataSource" ref="dataSource3"/>
<!-- configure to store the message body and following headers as text in the repo -->
<property name="storeBodyAsText" value="true"/>
<property name="headersToStoreAsText">
<list>
<value>companyName</value>
<value>accountName</value>
</list>
</property>
</bean>
46.16.1. コーデック (シリアル化) リンクのコピーリンクがクリップボードにコピーされました!
あらゆるタイプのペイロードを含めることができるため、エクスチェンジは設計上シリアライズできません。データベースのブロブフィールドに格納されるバイト配列に変換されます。これらの変換はすべて JdbcCodec クラスによって処理されます。コードの 1 つの詳細に注意する必要があります: ClassLoadingAwareObjectInputStream です。
ClassLoadingAwareObjectInputStream は、Apache ActiveMQ プロジェクトから再利用されています。ObjectInputStream をラップし、currentThread ではなく ContextClassLoader で使用します。利点は、他のバンドルによって公開されたクラスをロードできることです。これにより、交換の本文とヘッダーにカスタム型のオブジェクト参照を含めることができます。
46.16.2. Transaction リンクのコピーリンクがクリップボードにコピーされました!
トランザクションを調整するには、Spring PlatformTransactionManager が必要です。
46.16.2.1. Service (Start/Stop) リンクのコピーリンクがクリップボードにコピーされました!
start メソッドは、データベースの接続と必要なテーブルの存在を確認します。何か問題があると、起動時に失敗します。
46.16.3. アグリゲーターの設定 リンクのコピーリンクがクリップボードにコピーされました!
対象となる環境によっては、アグリゲーターに何らかの設定が必要になる場合があります。ご存知のように、各アグリゲーターには独自のリポジトリー (対応するテーブルのペアがデータベースに作成されている) とデータソースが必要です。デフォルトの lobHandler がデータベースシステムに適合していない場合は、lobHandler プロパティーを挿入できます。
Oracle の宣言は次のとおりです。
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler">
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
<bean id="repo"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
<property name="transactionManager" ref="transactionManager"/>
<property name="repositoryName" value="aggregation"/>
<property name="dataSource" ref="dataSource"/>
<!-- Only with Oracle, else use default -->
<property name="lobHandler" ref="lobHandler"/>
</bean>
46.16.4. Optimistic locking リンクのコピーリンクがクリップボードにコピーされました!
optimisticLocking をオンにして、複数の Camel アプリケーションが集約リポジトリー用の同じデータベースを共有するクラスター化された環境で、この JDBC ベースの集約リポジトリーを使用できます。競合状態がある場合、JDBC ドライバーは、JdbcAggregationRepository が対応できるベンダー固有の例外を出力します。JDBC ドライバーからの例外の原因が楽観的ロックエラーと見なされるかを知るには、これを行うマッパーが必要です。したがって、org.apache.camel.processor.aggregate.jdbc.JdbcOptimisticLockingExceptionMapper があり、必要に応じてカスタムロジックを実装できます。次のように動作するデフォルトの実装 org.apache.camel.processor.aggregate.jdbc.DefaultJdbcOptimisticLockingExceptionMapper があります。
次のチェックが行われます。
-
原因となった例外が
SQLExceptionの場合、SQLState が 23 で始まるかどうかがチェックされます。 -
原因となった例外が
DataIntegrityViolationExceptionの場合 - 発生した例外クラス名に ConstraintViolation が含まれる場合。
- クラス名が設定されている場合、FQN クラス名の一致をオプションでチェックします。
さらに、FQN クラス名を追加できます。発生した例外 (またはネストされた例外) のいずれかが FQN クラス名のいずれかと等しい場合は、楽観的ロックエラーになります。
以下は、JDBC ベンダーからの 2 つの追加の FQN クラス名を定義する例です。
<bean id="repo"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
<property name="transactionManager" ref="transactionManager"/>
<property name="repositoryName" value="aggregation"/>
<property name="dataSource" ref="dataSource"/>
<property name="jdbcOptimisticLockingExceptionMapper" ref="myExceptionMapper"/>
</bean>
<!-- use the default mapper with extraFQN class names from our JDBC driver -->
<bean id="myExceptionMapper" class="org.apache.camel.processor.aggregate.jdbc.DefaultJdbcOptimisticLockingExceptionMapper">
<property name="classNames">
<util:set>
<value>com.foo.sql.MyViolationExceptoion</value>
<value>com.foo.sql.MyOtherViolationExceptoion</value>
</util:set>
</property>
</bean>
46.16.5. 伝播動作 リンクのコピーリンクがクリップボードにコピーされました!
JdbcAggregationRepository は、Spring-TX の 2 つの異なる トランザクションテンプレート を使用します。1 つは読み取り専用で、もう 1 つは読み書き操作に使用されます。
ただし、それ自体が <transacted /> を使用するルート内で JdbcAggregationRepository を使用し、共通の PlatformTransactionManager が使用されている場合、JdbcAggregationRepository 内のトランザクションテンプレートによって使用される 伝播動作 を設定する必要がある場合があります。
これを行う方法は次のとおりです。
<bean id="repo"
class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
<property name="propagationBehaviorName" value="PROPAGATION_NESTED" />
</bean>
伝播は org.springframework.transaction.TransactionDefinitionインターフェイスの定数で指定されるので、propagationBehaviorName は定数の名前を使用できる便利なセッターです。
46.16.6. PostgreSQL の場合 リンクのコピーリンクがクリップボードにコピーされました!
JdbcAggregationRepository によって使用される楽観的ロックで問題を引き起こす可能性がある特別なデータベースがあります。PostgreSQL は、データ整合性違反の例外 (SQLState 23505 の例外) の場合、接続を無効としてマークします。これにより、ネストされたトランザクション内で接続が事実上使用できなくなります。詳細は ドキュメント に記載されています..
org.apache.camel.processor.aggregate.jdbc.PostgresAggregationRepository は JdbcAggregationRepository を拡張し、楽観的なロック動作を提供する特別な INSERT ..ON CONFLICT .. ステートメントを使用します。
このステートメントは次のとおりです (デフォルトの集計テーブル定義を使用)。
INSERT INTO aggregation (id, exchange) values (?, ?) ON CONFLICT DO NOTHING
詳細については、PostgreSQL のドキュメント を参照してください。
この節を使用すると、java.sql.PreparedStatement.executeUpdate() 呼び出しは、SQLState=23505 で SQLException を出力する代わりに 0 を返します。以降の処理は、一般的な JdbcAggregationRepository とまったく同じですが、PostgreSQL 接続を無効としてマークすることはありません。