マルチスレッド処理
Liferay DXP 7.4 U10+ または Liferay Portal 7.4 GA14+
アップグレード プロセス では、大規模なデータ セットに複雑な変更を加えることが必要になる場合があります。 パフォーマンスがクリティカルな場合は、アプリケーションのUpgradeProcessクラスのprocessConcurrently()メソッドを使用するようにしてください。 このメソッドは複数のスレッドで実行されるため、アップグレードの時間を短縮することができます。
バージョン1.0.0をデプロイする
新しいLiferay DXPインスタンスを起動し、以下を実行します。
docker run -it -m 8g -p 8080:8080 liferay/dxp:2025.q1.6-lts
メールアドレス test@liferay.com とパスワード testを使用して、 http://localhost:8080 で Liferay にサインインします。 プロンプトが表示されたら、パスワードを learnに変更します。
次に、以下の手順に従います。
-
マルチスレッド プロセスをダウンロードして解凍します。
curl https://resources.learn.liferay.com/examples/liferay-j7z3.zip -Ounzip liferay-j7z3.zip -
1.0.0ディレクトリに移動し、ビルドとデプロイを行います。cd 1.0.0../gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)注このコマンドは、デプロイされたjarをDockerコンテナの/opt/liferay/osgi/modulesにコピーするのと同じです。
-
Liferay Dockerコンテナコンソールでデプロイを確認します。
STARTED com.acme.j7z3.api_1.0.0 [1030] STARTED com.acme.j7z3.service_1.0.0 [1031]
アプリにエントリーを追加する
-
コントロール パネル → サーバー管理 → スクリプトでスクリプト コンソールに移動します。
-
以下のスクリプトを実行して、いくつかのエントリーを追加してください。
import com.acme.j7z3.service.J7Z3EntryLocalServiceUtil; import com.liferay.portal.kernel.dao.orm.QueryUtil; entry1 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(1); entry2 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(2); entry3 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(3); entry1.setName("able"); entry2.setName("able"); entry3.setName("able"); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry1); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry2); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry3);J7Z3_J7Z3Entryテーブルには、3つのエントリーが追加されました。

アップグレードの実行
-
1.0.1ディレクトリに移動し、ビルドとデプロイを行います。cd ../1.0.1../gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq) -
コントロール パネル → Gogo Shellで Gogo Shell コンソールに移動します。
-
upgrade:list com.acme.j7z3.serviceというコマンドを入力し、1.0.1へのアップグレードが可能であることを確認します。 1.0.1バージョンは、出力ウィンドウに登録されたアップグレードプロセスとして表示されます。 -
upgrade:execute com.acme.j7z3.serviceというコマンドを入力して、アップグレードを実行します。 [出力]ウィンドウには、アップグレードが完了したことが表示されます。
-
J7Z3_J7Z3Entryテーブルのエントリーが更新されました。

マルチスレッドメソッドの実装
アプリケーションのUpgradeProcessクラスで、processConcurrently()メソッドをオーバーライドしてください。
@Override
protected void doUpgrade() throws Exception {
processConcurrently(
"select j7z3EntryId, name from J7Z3_J7Z3Entry",
resultSet -> new Object[] {
resultSet.getLong("j7z3EntryId"), resultSet.getString("name")
},
columns -> {
long j7z3EntryId = (Long)columns[0];
try (PreparedStatement preparedStatement =
connection.prepareStatement(
"update J7Z3_J7Z3Entry set name = ? where " +
"j7z3EntryId = ?")) {
preparedStatement.setString(1, "baker");
preparedStatement.setLong(2, j7z3EntryId);
preparedStatement.executeUpdate();
}
},
null);
}
メソッドは4つのパートで構成されています。
-
SQLクエリ - データベースのデータを照会するためのSQL文。
-
オブジェクトを収集する - 結果セットを受け取り、結果セットに基づいたオブジェクトの配列を返します。
-
オブジェクトの処理 - オブジェクトの配列に対してビジネスロジックを実行します。
-
例外 - 例外が発生した場合、メッセージを送信します。
サンプルプロジェクトでは、 nameフィールドを processConcurrently()メソッドで処理・変更する簡単な例を示しました。
-
select j7z3EntryId, name from J7Z3_J7Z3Entry- SQL文はすべてのエントリーを照会します。 -
resultSet -> new Object[] { resultSet.getLong("j7z3EntryId"), resultSet.getString("name") }オブジェクトは集められ、
resultSet配列に格納されます。 -
columns -> { long j7z3EntryId = (Long)columns[0]; try (PreparedStatement preparedStatement = connection.prepareStatement( "update J7Z3_J7Z3Entry set name = ? where " + "j7z3EntryId = ?")) { preparedStatement.setString(1, "baker"); preparedStatement.setLong(2, j7z3EntryId); preparedStatement.executeUpdate(); } }j7z3EntryIdごとに、nameフィールドをbakerに設定しています。 -
例外は、
nullに設定されます。
processConcurrently()の代替実装
processConcurrently() メソッドには、2 つの代替シグネチャがあります。 1 つ目は、パフォーマンスを向上させるために自動バッチ処理を使用します。 J7Z3EntryUpgradeProcess.java ファイルで、 processConcurrently() の使用箇所を次のコードに置き換えます。
processConcurrently(
"select j7z3EntryId, name from J7Z3_J7Z3Entry",
"update J7Z3_J7Z3Entry set name = ? where j7z3EntryId = ?",
resultSet -> new Object[] {
resultSet.getLong("j7z3EntryId"), resultSet.getString("name")
},
(columns, preparedStatement) -> {
long j7z3EntryId = (Long)columns[0];
preparedStatement.setString(1, "baker");
preparedStatement.setLong(2, j7z3EntryId);
preparedStatement.addBatch();
},
null);
この署名には次のパラメータがあります。
-
元の実装と同様に、最初の引数は処理するデータを取得するための SQL クエリです。
-
2 番目の引数は、メソッドによって制御されるバッチでデータを挿入、更新、または削除するための SQL クエリです。
-
3 番目の引数は、元の実装の関数に似た関数です。
resultSet -> new Object[] { resultSet.getLong("j7z3EntryId"), resultSet.getString("name") } -
4 番目の引数も同様の関数です。
(columns, preparedStatement) -> { long j7z3EntryId = (Long)columns[0]; preparedStatement.setString(1, "baker"); preparedStatement.setLong(2, j7z3EntryId); preparedStatement.addBatch(); } -
最後の引数は、例外が発生した場合に使用される
文字列です。
SQL データの更新または挿入のみを行う単純なアップグレードには、このシグネチャを使用します。 データの挿入以上の処理 (ファイルの削除や画像の追加など) を行うアップグレードには、 以前の署名 を使用します。
もう一つのシグネチャはソースとして配列を渡します。 詳細については、 BaseDBProcess javadocs を参照してください。