jBatch(Batchlet & Chunk)+JPA2.1(Entity & JPQL)でデータ読み書き
JavaEE7で追加されたjBatch(JSR-352)とJPA2.1(JSR-338)を使用して、DBのデータを読み書きする。
【やること】
・jBatchのBatchlet方式とChunk方式を両方使ってバッチジョブを実行する。
・JPAのうち、SELECTはJPQL、INSERT,UPDATE,DELETEはEntity方式を使用してデータの読み書きをする。
処理概要は下図の通り。
【環境】
●Java
・jdk1.8.0_25
・Oracle Enterprise Pack for Eclipse (12.1.3.3.1) ※中身はLuna SR1 (4.4.1)
・GlassFish Server Open Source Edition 4.1
●JPA
・Eclipselink 2.5.2-RC1 ※GlassFish組み込み
●DB・JDBC
・PostgreSQL 9.0
・JDBC41 Postgresql Driver, Version 9.3-1102
●ツール
・pgAdminⅢ
【準備】
・JDBCをGlassfishのクラスパスが通る場所(libフォルダ)に置いた。
・srcフォルダ配下にMETA-INFフォルダを作り、その中に「batch-jobs」フォルダを作った。
・GlassfishにてJNDIデータソースを設定済。
[参考]GlassfishでJNDIデータソースの設定方法その1 - しんさんの出張所 はてな編
・データ読み書き用のテーブルを作成済。
CREATE TABLE employees ( empno integer NOT NULL, ename character varying(10), yomi character varying(20), job character varying(8), mgr integer, hiredate date, sal character varying(7), comm character varying(7), deptno integer, CONSTRAINT pk_emp PRIMARY KEY (empno) ) WITH ( OIDS=FALSE );
【資産 - 定義体】
1.emp-batch.xml
・バッチジョブの実行順序を記述
2.persistence.xml
・JPA定義+DB接続先情報
・"eclipselink.logging.level.sql"を"FINE"とすると生成されたSQLが見える
【資産 - ソースファイル】
1.InsertEmpInfoBatchlet.java
・データ入力役
・従業員番号2001番・太郎くんの情報をINSERTする。 ※入力データはハードコーディングした。
2.EmpInfoReader.java
・データ読み込み役
・従業員番号2001番・太郎くんの情報をSELECTする。
・1件取得する場合はTypedQuery#getSingleResultを使用する。
3.EmpInfoProcessor.java
・データ加工役
・SELECTしたデータに数値を設定する。入力データに意味はない
4.EmpInfoWriter.java
・データ書き込み役
・EmpInfoProcessorで加工したデータを適用し、UPDATEする。
5.DeleteEmpInfoBatchlet.java
・データ消去役
・従業員番号2001番・太郎くんの情報をDELETEする。
6.BatchServlet.java
・バッチジョブを実行する。
作成したプロジェクトのトップページは以下。
hhhhhskw/EmpInfoBatch · GitHub
【実行ログ】
2015-02-11T15:07:09.847+0900|情報: EmpInfoBatch was successfully deployed in 5,035 milliseconds. 2015-02-11T15:07:26.098+0900|情報: id = 50 2015-02-11T15:07:26.271+0900|情報: InsertEmpInfoBatchlet#process 2015-02-11T15:07:26.393+0900|普通: INSERT INTO employee (empno, comm, deptno, ename, hiredate, job, mgr, sal, yomi) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) bind => [9 parameters bound] 2015-02-11T15:07:26.493+0900|情報: JTS5014: Recoverable JTS instance, serverId = [100] 2015-02-11T15:07:26.572+0900|情報: EmpInfoReader#open 2015-02-11T15:07:26.574+0900|情報: EmpInfoWriter#open 2015-02-11T15:07:26.578+0900|情報: EmpInfoReader#readItem 2015-02-11T15:07:26.770+0900|情報: EmpInfoProcessor#processItem 2015-02-11T15:07:26.772+0900|情報: EmpInfoWriter#writeItems 2015-02-11T15:07:26.772+0900|情報: persistEmployee 2015-02-11T15:07:26.772+0900|情報: EmpInfoReader#checkpointInfo 2015-02-11T15:07:26.783+0900|情報: EmpInfoWriter#checkpointInfo 2015-02-11T15:07:26.791+0900|普通: UPDATE employee SET comm = ? WHERE (empno = ?) bind => [2 parameters bound] 2015-02-11T15:07:26.823+0900|情報: EmpInfoReader#readItem 2015-02-11T15:07:26.824+0900|情報: EmpInfoReader#checkpointInfo 2015-02-11T15:07:26.835+0900|情報: EmpInfoWriter#checkpointInfo 2015-02-11T15:07:26.842+0900|情報: EmpInfoReader#close 2015-02-11T15:07:26.843+0900|情報: EmpInfoWriter#close 2015-02-11T15:07:26.886+0900|情報: DeleteEmpInfoBatchlet#process#begin 2015-02-11T15:07:26.906+0900|普通: UPDATE employee SET comm = ?, deptno = ?, ename = ?, hiredate = ?, job = ?, mgr = ?, sal = ?, yomi = ? WHERE (empno = ?) bind => [9 parameters bound] 2015-02-11T15:07:26.926+0900|普通: DELETE FROM employee WHERE (empno = ?) bind => [1 parameter bound] 2015-02-11T15:07:26.926+0900|情報: DeleteEmpInfoBatchlet#process#commit
【つまったところなど】
・バッチ処理で無限ループした時はItemReaderの実装をまず疑う。
→readItemメソッドの戻り値にnullが設定されるコードになってるか、チェックポイントをカウントする実装はおかしくないかetc
・JPQL使用時のコードでPSQLExceptionが発生する場合は、9割方文法が間違っている(体感)。
→SELECT句のカラム名に「*」を設定していないか、FROM句にEntityクラス名を指定しているかetc
・EclipseからGlassfishへ資産をデプロイできない場合は、EclipseからGlassfishサーバーを一旦削除して、Glassfishサーバーを再度作成する。もしくはドメインフォルダ配下に生成された一時フォルダ・ファイルを削除する。
・それでもデプロイできないときは、Eclipseと端末の再起動
・Glassfish起動時にポート1527が開いていません的例外が出たら、JDK付属のJavaDBを起動したうえで、Glassfishを起動する。
[2015-01-27T23:52:11.436+0900] [glassfish 4.1] [WARNING] [poolmgr.create_resource_error] [javax.enterprise.resource.resourceadapter.com.sun.enterprise.resource.allocator] [tid: _ThreadID=47 _ThreadName=admin-listener(5)] [timeMillis: 1422370331436] [levelValue: 900] [[ RAR5038:Unexpected exception while creating resource for pool DerbyPool. Exception : javax.resource.spi.ResourceAllocationException: Connection could not be allocated because: java.net.ConnectException: ポート1527のサーバーlocalhostへの接続中にメッセージConnection refused: connectでエラーが発生しました。]]
【参考文献・URL】
The Java EE 7 TutorialのjBatchの章をテキトーに訳した - kagamihogeの日記
jBatchでデータロードしてみる - kagamihogeの日記
jbatch (JSR352) - Chunk方式のStepを使ってみる - @lbtc_xxx lab
Java EE6を使う
GitHubに間違ってあげてしまった過去のコミットを削除してみる|めっとぼ
Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava (Programmer’s SELECTION)
- 作者: Antonio Goncalves,日本オラクル株式会社,株式会社プロシステムエルオーシー
- 出版社/メーカー: 翔泳社
- 発売日: 2012/03/09
- メディア: 大型本
- 購入: 5人 クリック: 147回
- この商品を含むブログ (28件) を見る