第114章 MyBatis
MyBatis リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Camel 2.7 以降で利用可能
mybatis: コンポーネントを使用すると、MyBatis を使用して、リレーショナルデータベースでデータのクエリー、ポーリング、挿入、更新、および削除を行うことができます。
Maven ユーザーは、このコンポーネントの
pom.xml に以下の依存関係を追加する必要があります。
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mybatis</artifactId>
<version>2.17.0.redhat-630xxx</version>
<!-- use the same version as your Camel core version -->
</dependency>
URI 形式 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
mybatis:statementName[?options]
ここでの statementName は、評価するクエリー、挿入、更新、または削除の操作にマップする MyBatis XML マッピングファイルのステートメント名です。
URI にクエリーオプションは
?option=value&option=value&.. の形式で追加できます。
このコンポーネントはデフォルトで、想定される名前
SqlMapConfig.xml でクラスパスのルートから MyBatis SqlMapConfig ファイルをロードします。ファイルが別の場所にある場合は、MyBatisComponent コンポーネントで configurationUri オプションを設定する必要があります。
オプション リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
consumer.onConsume
|
文字列
|
null
|
消費後に実行するステートメント。たとえば、Camel で消費および処理された後に行を更新するために使用できます。後ほどサンプル を参照してください。複数のステートメントはコンマで区切ることができます。 |
consumer.useIterator
|
boolean
|
true
|
true の場合、ポーリングが個別に処理されるときに返される各行。false の場合、データの リスト 全体が IN ボディーとして設定されます。
|
consumer.routeEmptyResultSet
|
boolean
|
false
|
空の結果セットをルーティングすべきかどうかを設定します。 |
statementType
|
StatementType
|
null
|
呼び出す操作の種類を制御するためにプロデューサーに指定する必要があります。enum 値は SelectOne、SelectList、、Update、UpdateList、Delete、および DeleteList です。注記:InsertList は Camel 2.10 で利用可能で、Update Camel 2.11 で利用できます。
|
maxMessagesPerPoll
|
int
|
0
|
このオプションは、データベースプールによって返される結果をバッチに分割し、それらを複数のエクスチェンジで配信することを目的としています。この整数は、単一のエクスチェンジで配信する最大メッセージを定義します。デフォルトでは最大値は設定されていません。たとえば制限を 1000 などに設定して、数千のファイルがあるサーバーの起動を回避できます。無効にするには、0 または負の値を設定します。 |
executorType
|
文字列
|
null
|
Camel 2.11: ステートメントの実行中に使用されるエグゼキューターのタイプ。サポートされる値は、simple、re reuse、batch です。デフォルトでは、値は指定されず、MyBatis が使用するもの(つまり simple )と同じです。シンプルな エクゼキューターは特別なことを行いません。エグゼキューターを 再利用 すると、準備済みステートメントが再利用されます。バッチ エグゼキューターは、ステートメントとバッチの更新を再利用します。 |
outputHeader
|
文字列
|
null
|
Camel 2.15: メッセージのボディーではなくヘッダーとして結果を保存します。これにより、既存のメッセージボディーをそのまま保存できます。 |
inputHeader
|
文字列
|
null
|
Camel 2.15: ボディーの代わりにコンポーネントへの入力としてヘッダー値を使用します。 |
transacted
|
ブール値
|
false
|
Camel 2.16.2: SQL コンシューマーのみ。トランザクションを有効または無効にします。有効にすると、エクスチェンジの処理に失敗し、コンシューマーは追加のエクスチェンジを処理しなくなり、即時ロールバックが発生します。 |
メッセージヘッダー リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Camel は結果メッセージ(IN または OUT のいずれかのヘッダーに、使用する ステートメントが含まれるヘッダー)を入力します。
| ヘッダー | タイプ | 説明 |
|---|---|---|
CamelMyBatisStatementName
|
文字列
|
使用される statementName (例:insertAccount)。 |
CamelMyBatisResult
|
オブジェクト
|
いずれの操作でも MtBatis から返される 応答。たとえば、INSERT は自動生成キーや行数などを返すことができます。
|
メッセージボディー リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MyBatis からの応答は、
SELECT ステートメントの場合のみボディーとして設定されます。たとえば、INSERT ステートメントの場合、Camel はボディーを置き換えません。これにより、ルーティングを継続し、元のボディーを維持することができます。MyBatis からの応答は、常にキー CamelMyBatisResult を持つヘッダーに保存されます。
サンプル リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
たとえば、JMS キューから Bean を使用し、それらをデータベースに挿入する場合は、以下を実行できます。
from("activemq:queue:newAccount").
to("mybatis:insertAccount?statementType=Insert");
呼び出す操作の種類を Camel に指示する必要があるため、
statementType を指定する必要があることに注意してください。
insertAccount は、SQL マッピングファイルの MyBatis ID に置き換えます。
<!-- Insert example, using the Account parameter class -->
<insert id="insertAccount" parameterType="Account">
insert into ACCOUNT (
ACC_ID,
ACC_FIRST_NAME,
ACC_LAST_NAME,
ACC_EMAIL
)
values (
#{id}, #{firstName}, #{lastName}, #{emailAddress}
)
</insert>
StatementType を使用した MyBatis の制御の改善 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MyBatis エンドポイントにルーティングする場合、実行する SQL ステートメントが
SELECT、UPDATE、DELETE、または INSERT などであるかどうかを制御するために、より詳細な制御が必要になります。たとえば、IN ボディーに SELECT ステートメントへのパラメーターが含まれる MyBatis エンドポイントにルーティングする場合は、以下を実行できます。
from("direct:start")
.to("mybatis:selectAccountById?statementType=SelectOne")
.to("mock:result");
上記のコードでは、MyBatis ステートメント
selectAccountById を呼び出し、IN 本文に 整数 タイプなどの取得するアカウント ID が含まれる必要があります。
SelectList などの他の操作でも同じことができます。
from("direct:start")
.to("mybatis:selectAllAccounts?statementType=SelectList")
.to("mock:result");
また
UPDATE と同じです。ここでは、Account オブジェクトを IN ボディーとして MyBatis に送信できます。
from("direct:start")
.to("mybatis:updateAccount?statementType=Update")
.to("mock:result");
InsertList StatementType の使用 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Camel 2.10 以降で利用可能
mybatis では、for-each batch ドライバーを使用して複数の行を挿入できます。これを使用するには、マッパー XML ファイルで <foreach> を使用する必要があります。以下に例を示します。
<!-- Batch Insert example, using the Account parameter class -->
<insert id="batchInsertAccount" parameterType="java.util.List">
insert into ACCOUNT (
ACC_ID,
ACC_FIRST_NAME,
ACC_LAST_NAME,
ACC_EMAIL
)
values (
<foreach item="Account" collection="list" open="" close="" separator="),(">
#{Account.id}, #{Account.firstName}, #{Account.lastName}, #{Account.emailAddress}
</foreach>
)
</insert>
次に、以下のように
InsertList ステートメントタイプを使用する mybatis エンドポイントに Camel メッセージを送信することで、複数の行を挿入できます。
from("direct:start")
.to("mybatis:batchInsertAccount?statementType=InsertList")
.to("mock:result");
UpdateList StatementType の使用 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Camel 2.11 から利用可能
mybatis では、for-each batch ドライバーを使用して複数の行を更新できます。これを使用するには、マッパー XML ファイルで <foreach> を使用する必要があります。以下に例を示します。
<update id="batchUpdateAccount" parameterType="java.util.Map">
update ACCOUNT set
ACC_EMAIL = #{emailAddress}
where
ACC_ID in
<foreach item="Account" collection="list" open="(" close=")" separator=",">
#{Account.id}
</foreach>
</update>
次に、以下のように UpdateList ステートメントタイプを使用する mybatis エンドポイントに Camel メッセージを送信することで、複数の行を更新できます。
from("direct:start")
.to("mybatis:batchUpdateAccount?statementType=UpdateList")
.to("mock:result");
DeleteList StatementType の使用 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Camel 2.11 から利用可能
mybatis では、for-each batch ドライバーを使用して複数の行を削除できます。これを使用するには、マッパー XML ファイルで <foreach> を使用する必要があります。以下に例を示します。
<delete id="batchDeleteAccountById" parameterType="java.util.List">
delete from ACCOUNT
where
ACC_ID in
<foreach item="AccountID" collection="list" open="(" close=")" separator=",">
#{AccountID}
</foreach>
</delete>
次に、以下のように DeleteList ステートメントタイプを使用する mybatis エンドポイントに Camel メッセージを送信することにより、複数の行を削除できます。
from("direct:start")
.to("mybatis:batchDeleteAccount?statementType=DeleteList")
.to("mock:result");
InsertList、UpdateList、および DeleteList StatementTypes に関する通知 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
すべてのタイプのパラメーター(List、Map など)を mybatis に渡すことができ、エンドユーザーは、mybatis 動的クエリー 機能を利用して必要に応じて処理します。
スケジュールされたポーリングの例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
このコンポーネントはスケジュールされたポーリングをサポートするため、Polling Consumer として使用できます。たとえば、データベースを 1 分ごとにポーリングするには、以下を実行します。
from("mybatis:selectAllAccounts?delay=60000").to("activemq:queue:allAccounts");
その他のオプションは、ポーリング コンシューマーの ScheduledPollConsumer Options を参照してください。
以下の例では、Timer コンポーネントを使用して 30 秒ごとにデータベースをポーリングし、データを JMS キューに送信します。
from("timer://pollTheDatabase?delay=30000").to("mybatis:selectAllAccounts").to("activemq:queue:allAccounts");
MyBatis SQL マッピングファイルが使用される:
<!-- Select with no parameters using the result map for Account class. -->
<select id="selectAllAccounts" resultMap="AccountResult">
select * from ACCOUNT
</select>
onConsume の使用 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
このコンポーネントは、データが Camel によって消費および処理された 後 のステートメントの実行をサポートします。これにより、データベースで更新後の更新を行うことができます。すべてのステートメントは
UPDATE ステートメントである必要があることに注意してください。Camel は、名前をコンマで区切る必要がある複数のステートメントの実行をサポートします。
以下のルートは、consumeAccount ステートメントデータが処理されることを示しています。これにより、データベースの行のステータスを processed に変更できるため、2 回以上消費しないようにします。
from("mybatis:selectUnprocessedAccounts?consumer.onConsume=consumeAccount").to("mock:results");
および sqlmap ファイルのステートメントは、以下のようになります。
<select id="selectUnprocessedAccounts" resultMap="AccountResult">
select * from ACCOUNT where PROCESSED = false
</select>
<update id="consumeAccount" parameterType="Account">
update ACCOUNT set PROCESSED = true where ACC_ID = #{id}
</update>
トランザクションへの参加 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
camel-mybatis でトランザクションマネージャーを設定するには、標準の MyBatis
SqlMapConfig.xml ファイル外でデータベース設定を外部化する必要があるため、少し時間がかかる場合があります。
最初の部分では、
DataSource を設定する必要があります。通常、これは Spring プロキシーでラップする必要があるプール(DBCP または c3p0)です。このプロキシーは、Spring 以外の DataSource を使用して Spring トランザクションに参加できるようにします(MyBatis SqlSessionFactory はこれのみを行います)。
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg>
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="org.postgresql.Driver"/>
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/myDatabase"/>
<property name="user" value="myUser"/>
<property name="password" value="myPassword"/>
</bean>
</constructor-arg>
</bean>
これには、プロパティープレースホルダーを使用してデータベース設定を外部化できるようにする追加の利点があります。
その後、トランザクションマネージャーは、外部
DataSource を管理するように設定されます。
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- standard mybatis config file -->
<property name="configLocation" value="/META-INF/SqlMapConfig.xml"/>
<!-- externalised mappers -->
<property name="mapperLocations" value="classpath*:META-INF/mappers/**/*.xml"/>
</bean>
その後、camel-mybatis コンポーネントはそのファクトリーで設定されます。
<bean id="mybatis" class="org.apache.camel.component.mybatis.MyBatisComponent">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
最後に、トランザクション ポリシーはトランザクションマネージャーの上部に定義され、通常どおり使用できます。
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="txManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
<camelContext id="my-model-context" xmlns="http://camel.apache.org/schema/spring">
<route id="insertModel">
<from uri="direct:insert"/>
<transacted ref="PROPAGATION_REQUIRED"/>
<to uri="mybatis:myModel.insert?statementType=Insert"/>
</route>
</camelContext>