だいたいのバッチ

##だいたいバッチってこうだよね

テーブルからレコードを取得
↓
レコードをもとにビジネスロジック
↓
テーブルを更新


ということでだいたいこうだよねテンプレートを作ってみました

##凝縮版

```凝縮.java
package test;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test {

	/** 検索対象テーブルのEntity */
	class Entity {}
	/** APIのリクエストDTO */
	class Request {}
	/** APIのレスポンスDTO */
	class Response {}
	
	/** SELECT文 */
	public List<Entity> select(String slq) {
		return Arrays.asList(new Entity(), new Entity());
	}
	/** EntityをAPIリクエストのDTOに変換 */
	private final Function<Entity, Request> createRequest = entity -> new Test().new Request();
	/** APIをたたく */
	private final Function<Request, Response> callApi = req -> {
		try {
			// API実行メソッドを呼ぶ
			return new Test().new Response();
		} catch (Exception e) {
			return null;
		}
	};
	/** APIレスポンスDTOの情報をEntityにセット */
	private final Function<Response, Entity> setEntity = res -> new Test().new Entity();
	/** UPDATE文 */
	private final Consumer<Entity> update = sql -> {};

	/** 使ってみる */
	public void batchJob() {
		// ジョブ起動対象のレコードを取得
		List<Entity> records = select("検索条件");
		// ビジネスロジックを実行
		records.stream().map(createRequest).map(callApi).map(setEntity).forEach(update);
	}
}
```
内部処理全部カットしていますが、だいたいこうですよね

それではそれぞれの処理をしっかり書いたらどうなるのか見てみましょう

##ちゃんとした版

```batch.java
package test;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class BatchJob {
	
	// DI
	private EntityManager em;
	private EntityEjb entityEjb = new EntityEjb();
	private ApiFacade apiFacade = new ApiFacade();
	
	// レコード取得条件
	Long condition1 = new Long(0);
	String condition2 = new String();
	List<String> condition3 = new LinkedList<>();

	public void execute() {
		
		// 実行対象のレコードを取得
		List<Entity> targets = entityEjb.find(condition1, condition2, condition3);
		
		// リクエスト作成
		List<Info> infoList = Collections.synchronizedList(new LinkedList<>());
		targets.forEach(entity -> {
			Info info = new Info();
			info.setColum1(entity.getColum1());
			info.setColum2(entity.getColum2());
			info.setColum3(entity.getColum3());
			infoList.add(info);
		});
		Request req = new Request();
		req.setinfoList(infoList);
		
		try {
			// API実行
			Response res = apiFacade.callApi(req);
			
			// テーブル更新
			Entity entity = new Entity();
			entity.setColum1(res.getColum1());
			entity.setColum2(res.getColum2());
			entity.setColum3(res.getColum3());
			em.merge(entity);
			
		} catch (Exception e) {
		}
	}
}
```

EntityManager関連は便利なものみ抽出してみました
以下にまとめます

```EntityManager.java
package test;

public interface EntityManager {

	/** sql文と検索結果クラスを引数にクエリを作成 */
	<T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass);
	
	/** 引数のエンティティの状態を現在の永続化コンテキストにマージ */
	<T> T merge(T entity);
}
```

```TypedQuery.java
package test;

import java.util.List;

public interface TypedQuery<X> {

	/** クエリのnameにvalueをセット */
	TypedQuery<X> setParameter(String name, Object value);
	
	/** クエリ実行結果をリストとして取得 */
	List<X> getResultList();
}
```

SELECT文の使用例

```select.java
package test;

import java.util.List;

public class EntityEjb {
	
	/** 永続化コンテキスト対話用インタフェース(javax.persistence.EntityManager) */
	private EntityManager em;// 今回は自作した

	/**
	 * 検索条件をもとにレコードを取得する.
	 * <p>
	 * 取得結果が存在しない場合は空のリストを返却.
	 * 
	 * @param condition1 検索条件1
	 * @param condition2 検索条件2
	 * @param condition3 検索条件3
	 * @return 取得結果
	 */
	public List<Entity> find(Long condition1, String condition2, List<String> condition3) {
		
		String jpql = "SELECT xxx FROM entity xxx "
				+ "WHERE colum1 = :condition1 "
				+ "AND colum2 = :condition2 "
				+ "AND colum3 IN :condition3";
		
		return em.createQuery(jpql, Entity.class)
				.setParameter("condition1", condition1)
				.setParameter("condition2", condition2)
				.setParameter("condition3", condition3)
				.getResultList();
	}
}
```

ちょっとJpqlに触れる機会が多かったので、EnttiyManagerを用いた永続化コンテキストが便利すぎて病みつきです