目次
バッチアプリケーションをJavaで開発した際に、
1. まずJPAとは
以下、wikipediaの一部を引用させていただきます
フルネームは「Java Persistence API」です。
2. エンティティマネージャについて
自分の理解としては、JavaプログラムとDBの間に構築されるエンティティを管理する部分。
基本的にはJavaプログラムからはDBに直接SQLを発行するのではなく、エンティティマネージャに対して操作を行う。
トランザクションが終了した時点でエンティティマネージャとDBが同期されて、DBに反映される。
3. データベース接続部分
※エンティティマネージャーを作成しています
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 対象のDBへ接続を行うためのEntityManagerを管理する
*/
public class DataSourceManager {
/** エンティティマネージャファクトリ */
private EntityManagerFactory entityManagerFactory;
/** エンティティマネージャ */
private EntityManager entityManager;
/** persistence-unit名の固定部 */
private String persistenceUnitNameFixedPart;
/** 実行環境 */
private String env;
/** ロガー */
private static final Logger LOGGER = LoggerFactory.getLogger("DataSourceManager.class");
/**
* コンストラクタ
* @param persistenceUnitNameFixedPart
* persistence-unit名の固定部
* @param env
* 実行環境
*/
protected DataSourceManager(String persistenceUnitNameFixedPart, String env) {
this.persistenceUnitNameFixedPart = persistenceUnitNameFixedPart;
this.env = env.toLowerCase();
}
/**
* DBへ接続する
*/
public void connect() {
if (this.env.equals(AppConsts.ENV_DEV)) {
LOGGER.debug("ローカル環境へのコネクションを確立します....");
createEntityManager();
} else if (this.env.equals(AppConsts.ENV_TEST)) {
LOGGER.debug("テスト環境へのコネクションを確立します....");
createEntityManager();
} else if (this.env.equals(AppConsts.ENV_PRODUCTION)) {
LOGGER.debug("本番環境のへのコネクションを確立します....");
createEntityManager();
} else {
LOGGER.debug("コネクション確立失敗....");
LOGGER.debug("環境変数設定に誤りがあります。");
String errorMsg = SingletonPropertiesLoader.getProperties(AppConsts.PROP_MESSAGES)
.getProperty([メッセージコード]);
//例外を発生させる
}
LOGGER.debug("コネクション確立完了");
}
/**
* EntityManagerインスタンスの生成
* @param dataSource
* @param env
*/
synchronized private void createEntityManager() {
String persistenceUnitName = getPersistenceUnitName();
LOGGER.debug("PersistenceUnitName: " + persistenceUnitName);
if (this.entityManagerFactory == null) {
// EntityManagerFactoryのみしか開いていない場合
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
entityManager = entityManagerFactory.createEntityManager();
}
if (this.entityManagerFactory != null && this.entityManager == null) {
// EntityManagerFactoryは開いているがとEntityManagerが開いていない場合
entityManager = entityManagerFactory.createEntityManager();
}
}
/**
* @param dataSource
* @param env
* @return
*/
private String getPersistenceUnitName() {
return this.persistenceUnitNameFixedPart + "_" + this.env;
}
/**
* EntityManagerを取得する
* @return entityManager
*/
public EntityManager getEntityManager() {
return entityManager;
}
/**
* DBコネクションを閉じる
*/
synchronized public void close() {
if (this.entityManager != null) {
if (this.entityManager.isOpen()) {
entityManager.close();
LOGGER.debug("EntityManagerクローズ完了");
}
}
if (this.entityManager != null) {
if (entityManagerFactory.isOpen()) {
entityManagerFactory.close();
LOGGER.debug("EntityManagerFactoryクローズ完了");
}
}
}
}
4.上記クラスを継承して作成したMySQL操作を行うクラス
※開発者に使いやすいようにjpaの実装をラップしている
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.TransactionRequiredException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* DB操作するための機能を管理する
*/
public class MySqlOperator extends DataSourceManager {
/** ロガー */
private static final Logger LOGGER = LoggerFactory.getLogger("MySqlConnector.class");
/**
* コンストラクタ
*/
protected MySqlOperator() throws BatchApplicationException {
super(PERSISTENCE_UNIT, System.getenv("GNAVIENV"));
}
/**
* DBへInsert文を発行する
* @param entity
* @throws EntityExistsException
* エンティティがすでに存在する場合
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
* @throws TransactionRequiredException
* トランザクションが存在しない場合
*/
public <T> void insert(T entity)
throws EntityExistsException, IllegalArgumentException, TransactionRequiredException {
getEntityManager().getTransaction().begin();
getEntityManager().persist((T) entity);
getEntityManager().getTransaction().commit();
}
/**
* DBへUpdate文を発行する
* @param entity
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
* @throws TransactionRequiredException
* トランザクションが存在しない場合
*/
public <T> void update(T entity) throws IllegalArgumentException, TransactionRequiredException {
getEntityManager().getTransaction().begin();
getEntityManager().merge(
(T) entity
);
getEntityManager().getTransaction().commit();
}
/**
* @param entity
* @return
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
*/
public <T> T select(T entity) throws IllegalArgumentException {
T getEntity = (T) getEntityManager().find(entity.getClass(), (T) entity);
return getEntity;
}
/**
* @param entity
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
* @throws TransactionRequiredException
* トランザクションが存在しない場合
*/
public <T> void delete(T entity) throws IllegalArgumentException, TransactionRequiredException {
getEntityManager().getTransaction().begin();
getEntityManager().remove(
(T) entity
);
getEntityManager().getTransaction().commit();
}
/**
* DBへInsert文を発行する
* @param entity
* @throws EntityExistsException
* エンティティがすでに存在する場合
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
* @throws TransactionRequiredException
* トランザクションが存在しない場合
*/
public <T> void insert(List<T> entities)
throws EntityExistsException, IllegalArgumentException, TransactionRequiredException {
getEntityManager().getTransaction().begin();
entities.forEach(entity -> getEntityManager().persist(
(T) entity)
);
getEntityManager().getTransaction().commit();
}
/**
* DBへUpdate文を発行する
* @param entity
* @throws IllegalArgumentException
* インスタンスがエンティティでない場合
* @throws TransactionRequiredException
* トランザクションが存在しない場合
*/
public <T> void update(List<T> entities) throws IllegalArgumentException, TransactionRequiredException {
getEntityManager().getTransaction().begin();
entities.forEach(entity -> getEntityManager().merge(
(T) entity)
);
getEntityManager().getTransaction().commit();
}
}
5.シングルトンでMySQLのコネクターを管理する
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* MySqlへのコネクションをシングルトンで管理する
*/
public class SingletonMySqlConnector {
/** MySqlOperatorインスタンス */
private static MySqlOperator singletonMySqlOperator = new MySqlOperator();
/** ロガー */
private static final Logger LOGGER = LoggerFactory.getLogger("SingletonMySqlConnector.class");
/**
* 不可視コンストラクタ
*/
private SingletonMySqlConnector() {
}
/**
* MySqlOperatorインスタンスを取得する
* @return
*/
public static MySqlOperator getInstance() {
return singletonMySqlOperator;
}
}
6.設定ファイル(persistence.xml)
※読み込ませるには以下のディレクトリ構造でなくてはいけない。
./resources/META-INF/persistence.xml
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<!-- MySQL設定 -->
<persistence-unit name="sai_mysql" transaction-type="RESOURCE_LOCAL">
※eclipselink-2.6.4.jar内のPersistenceProviderクラスをフルパスで指定
<class>com.example.entity.SampleEntity</class>
<properties>
<!-- 開発用DBのため、SSL接続を無効に設定している -->
※以下を設定しておくと生成されたSQLをログに出力してくれる
※なんの設定か忘れましたが確か必要でした。
<property name="toplink.platform.class.name" value="oracle.toplink.essentials.platform.database.DerbyPlatform" />
</properties>
</persistence-unit>
</persistence>
7.エンティティクラスの作成
「jpa エンティティクラス」とかで調べれば出てくるのでここは割愛します。
8.必要jar
※jarの参照順に注意すること、以下の順番で参照していれば問題なし。
・javax.persistence-2.1.1.jar
・toplink-essentials-2.1-60.jar
・eclipselink-2.6.4.jar
・validation-api-1.1.0.Final.jar
以上