#% モデル・仮想データベーステーブル・ファイルクリエータープラグイン
#! package
package #package#;
#! header

#loggerComment#import org.apache.log4j.Logger;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

/**
 * #nameJp# モデル・仮想データベーステーブルアクセスクラス<br>
 * <br>
 * このモデルの機能を拡張する場合はこのクラスと同じパッケージに<br>
 * このクラスを派生させた#className#Exクラスを作成することにより<br>
 * 行うことが可能です。<br>
 * <br>
 * このクラスのgetInstanceメソッドは#className#Exが存在すると<br>
 * そのインスタンスを戻します。<br>
 * <br>
 * #className#Exが存在しなければ#className#クラスのインスタンスを<br>
 * 戻します。<br>
 *
 * @author
 *
 */
@SuppressWarnings("serial")
public class #className# implements Serializable {

	/** DAO用トランザクション */
	private DaoTransaction daoTransaction = null;

	/** 外部トランザクションフラグ */
	private boolean outerTransactionFlag;

	/** このクラスまたは拡張クラスのClassオブジェクト	*/
	private static Class<?> myClass = null;

	static{
		try {
			myClass = Class.forName((#className#.class.getPackage() == null ? "" : #className#.class.getPackage().getName() + ".") + "#className#Ex");
			if(!#className#.class.isAssignableFrom(myClass)){
				myClass = #className#.class;
			}
		} catch (ClassNotFoundException e) {
			myClass = #className#.class;
		}
	}

	// ロガー
	#loggerComment#private static Logger logger = Logger.getLogger(#className#.class);

	/**
	 * new禁止コンストラクタ
	 */
	protected #className#() {
		//	何もしない
	}

#! insert start
	/**
	 * #nameJp#に1レコード挿入する<BR>
	 * リンクされている子テーブルの挿入時にユニークインデックス又は主キーエラーが発生したときはSQLExceptionがスローされる
	 * @param rec
	 *            #nameJp#
	 * @return 主キーが存在するテーブルの挿入件数（ユニークインデックス又は主キーエラー時は0）
	 * @throws SQLException
	 */
	public int insert(#voName# record_insert) throws SQLException {
		#loggerComment#logger.info("#nameJp# model : insert : " + record_insert.toString());
		int ret = 0;
		try {

			// DAOまたはモデル作成
#! insert dao model Dao
			#daoClassName# #daoName# = new #daoClassName#(getDaoTransaction());
#! insert dao model Model
			#daoClassName# #daoName# = #daoClassName#.getInstance(getDaoTransaction());
#! insert main root

			// #nameJp#（主キーが存在するテーブル） 挿入 //////////////////////////////
			ret = #daoName#.insert(record_insert.#recordGetter#());
			if(ret <= 0){
				return ret;
			}

#! insert main 1
			// #nameJp# 挿入 (既にデータが存在していたら更新を行う) //////////////////////////////
			if(record_insert.#recordGetter#() != null	//
#! insert key check
				&& record_insert.#recordGetter#() != null && record_insert.#recordGetter#().#getter#() != null	//
#! insert main 1.5
			){
#! insert key set
				record_insert.#recordSetter#().#setter#(record_insert.#recordGetter#().#getter#());
#! insert main 2
				if(#daoName#.update(record_insert.#recordGetter#()) < 1){
					if(#daoName#.insert(record_insert.#recordGetter#()) < 1){
						throw new SQLException("リンクされているテーブルのインサートに失敗しました #nameJp#");
					}
				}
			}

#! insert main multi 1
			// #nameJp#（リスト） 追加 //////////////////////////////
			#multiName# record_key_#name# = null;
			if(record_insert.#recordGetter#() != null	//
#! insert main multi 2
				&& record_insert.#recordGetter#().#getter#() != null	//
#! insert main multi 3
			){
				for (#multiName# record_rec : record_insert.#recordGetter#()) {
#! insert main multi 4
					record_rec.#setter#(record_insert.#recordGetter#().#getter#());
#! insert main multi 5
				}
				record_key_#name#  = new #multiName#();
#! insert main multi 5.2
				record_key_#name# .#setter#(record_insert.#recordGetter#().#getter#());
#! insert main multi 5.4
			}else{
				 record_insert.#recordGetter#().clear();
			}

#! insert main multi 6
			//	すでに存在している同一リンクキーのデータを削除
			if(record_key_#name#  != null){
				for (#multiName# record_DbRec : #daoName#.getPrimaryKeys(record_key_#name#)) {
					#daoName#.delete(record_DbRec);
				}
			}

			// 挿入
			for (#multiName# record_rec : record_insert.#recordGetter#()) {
				if(#daoName#.insert(record_rec) < 1){
					throw new SQLException("リンクされているテーブルのインサートに失敗しました #nameJp#");
				}
			}

#! insert end
			commitDaoTransaction();

			#loggerComment#logger.info("insert 結果 = " + ret);
			return ret;

		} finally {
			closeDaoTransaction();
		}
	}

#! update start
	/**
	 * #nameJp#を更新する<BR>
	 * リンクされている子テーブルの更新（非存在時の挿入）件数が0の時はSQLExceptionがスローされる
	 * @param rec
	 *            #nameJp#
	 * @return 主キーが存在するテーブルの更新件数
	 * @throws SQLException
	 */
	public int update(#voName# record_update) throws SQLException {
		#loggerComment#logger.info("#nameJp# model : update :" + record_update.toString());
		int ret = 0;
		try {

			// DAOまたはモデル作成
#! update dao model Dao
			#daoClassName# #daoName# = new #daoClassName#(getDaoTransaction());
#! update dao model Model
			#daoClassName# #daoName# = #daoClassName#.getInstance(getDaoTransaction());
#! update main root

			// 現データの読み込み
			#voName# record_now = (#className#.getInstance(getDaoTransaction())).get(record_update);
#! update main root 1

			// #nameJp#（主キーが存在するテーブル） 更新 //////////////////////////////
			ret = #daoName#.update(record_update.#recordGetter#());
			if(ret < 1){
				return ret;
			}

#! update main 1
			// #nameJp# 更新 //////////////////////////////
			if(record_update.#recordGetter#() != null	//
#! update main key check
				&& record_update.#recordGetter#() != null && record_update.#recordGetter#().#getter#() != null	//
#! update main 2
			){
#! update key set
				record_update.#recordSetter#().#setter#(record_update.#recordGetter#().#getter#());
#! update main 3
			}else{
				record_update.#recordSetter#(null);
			}

#! update main del
			// キーの値が違うときは現データ削除（1:1対応）
			if(record_now != null && record_now.#recordGetter#() != null //
				&& !record_now.#recordGetter#().equalsPrimaryKeys(record_update.#recordGetter#())){
				#daoName#.delete(record_now.#recordGetter#());
			}

#! update main 4
			// 更新
			if(record_update.#recordGetter#() != null){
				if(#daoName#.update(record_update.#recordGetter#()) < 1){
					if(#daoName#.insert(record_update.#recordGetter#()) < 1){
						throw new SQLException("リンクされているテーブルのアップデートに失敗しました #nameJp#");
					}
				}
			}

#! update main multi 1
			// #nameJp#（リスト） 更新 //////////////////////////////
			#multiName# record_key_#name# = null;
			if(record_update.#recordGetter#() != null	//
#! update main multi 2
				&& record_update.#recordGetter#().#getter#() != null	//
#! update main multi 3
			){
				for (#multiName# record_rec : record_update.#recordGetter#()) {
#! update main multi 4
					record_rec.#setter#(record_update.#recordGetter#().#getter#());
#! update main multi 5
				}
				record_key_#name#  = new #multiName#();
#! update main multi 5.2
				record_key_#name# .#setter#(record_update.#recordGetter#().#getter#());
#! update main multi 5.4
			}else{
				 record_update.#recordGetter#().clear();
			}

#! update main multi del
			//	リンクキー変更時の現データ削除（1:n対応）
			for (#multiName# record_nowRec : record_now.#recordGetter#()) {
				boolean deleteFlag = true;
				for(#multiName# record_rec : record_update.#recordGetter#()){
					if(record_rec.equalsPrimaryKeys(record_nowRec)){
						deleteFlag = false;
						break;
					}
				}
				if(deleteFlag){
					#daoName#.delete(record_nowRec);
				}

			}

#! update main multi 6
			//	リスト内で削除されたデータの削除
			if(record_key_#name#  != null){
				for (#multiName# record_DbRec : #daoName#.getPrimaryKeys(record_key_#name# )) {
					boolean deleteFlag = true;
					for (#multiName# record_rec : record_update.#recordGetter#()) {
						if (record_rec.equalsPrimaryKeys(record_DbRec)) {
						deleteFlag = false;
						break;
						}
					}
					if(deleteFlag){
						#daoName#.delete(record_DbRec);
					}
				}
			}

			// 更新
			for (#multiName# record_rec : record_update.#recordGetter#()) {
				if (#daoName#.update(record_rec) < 1) {
					if(#daoName#.insert(record_rec) < 1){
						throw new SQLException("リンクされているテーブルのアップデートに失敗しました #nameJp#");
					}
				}
			}

#! update end
			commitDaoTransaction();

			#loggerComment#logger.info("update 結果 = " + ret);
			return ret;

		} finally {
			closeDaoTransaction();
		}
	}

#! delete start
	/**
	 * #nameJp#を削除する
	 *
	 * @param record_deleteKey
	 *            #nameJp#
	 * @return 主キーが存在するテーブルの削除件数
	 * @throws SQLException
	 */
	public int delete(#voName# record_deleteKey) throws SQLException {
		#loggerComment#logger.info("#nameJp# model : delete : " + record_deleteKey.toString());
		int ret = 0;
		try {

			// DAOまたはモデル作成
#! delete dao model Dao
			#daoClassName# #daoName# = new #daoClassName#(getDaoTransaction());
#! delete dao model Model
			#daoClassName# #daoName# = #daoClassName#.getInstance(getDaoTransaction());
#! delete main root

			// 現データの読み込み //////////////////////////////
			#voName# record_delete = (#className#.getInstance(getDaoTransaction())).get(record_deleteKey);
			if(record_delete == null){
				return 0;
			}

			// #nameJp#（主キーが存在するテーブル） 削除 //////////////////////////////
			ret = #daoName#.delete(record_delete.#recordGetter#());
			if(ret <= 0){
				return ret;
			}

#! delete main
			// #nameJp# 削除 //////////////////////////////
			if(record_delete.#recordGetter#() != null){	//
				#daoName#.delete(record_delete.#recordGetter#());	// 削除件数チェックは行わない
			}

#! delete main multi
			// #nameJp# 全レコードを削除 //////////////////////////////
			for (#multiName# record_rec : record_delete.#recordGetter#()) {
				#daoName#.delete(record_rec);
			}

#! delete end
			commitDaoTransaction();

			#loggerComment#logger.info("delete 結果 = " + ret);
			return ret;

		} finally {
			closeDaoTransaction();
		}
	}

#! get start
	/**
	 * #nameJp# 取得
	 *
	 * @return 検索された#nameJp#
	 * @throws SQLException
	 */
	public #voName# get(#voName# record_keyRecord) throws SQLException {
		#loggerComment#logger.info("#nameJp# model : get : " + record_keyRecord.toString());
		#voName# record_rec = null;

		// 主キーチェック
#! get check key set
		if(record_keyRecord.#getMethod#() == null){
			return record_rec;
		}

#! get dao model start
		try {

			// DAOまたはモデル作成
#! get dao model Dao
			#daoClassName# #daoName# = new #daoClassName#(getDaoTransaction());
#! get dao model Model
			#daoClassName# #daoName# = #daoClassName#.getInstance(getDaoTransaction());
#! get main root

			// #nameJp#（主キーが存在するテーブル） 取得 //////////////////////////////
			#getClassName# #recordName# = #daoName#.get(record_keyRecord.#recordGetter#());
			if (#recordName# == null) {
				return record_rec;
			}
			record_rec = new #voName#();
			record_rec.#recordSetter#(#recordName#);

#! get main 1
			// #nameJp# 取得 //////////////////////////////
			if(record_rec.#recordGetter#() != null //
#! get key check
				&& record_rec.#recordGetter#().#getter#() != null	//
#! get main 1.5
			){
				#className# #recordName#Key = new #className#();
#! get main key
				#recordName#Key.#setter#(record_rec.#recordGetter#().#getter#());
#! get main 2
				record_rec.#recordSetter#(#daoName#.get(#recordName#Key));
			}

#! get main multi 1
			// 複数レコードを取得 //////////////////////////////
			record_rec.#multiRecordGetter#().clear();
			if(record_rec.#recordGetter#() != null	//
#! get multi key check
				&& record_rec.#recordGetter#().#getter#() != null	//
#! get main multi 2
			){
				#multiName# record_key = new #multiName# ();
#! get main multi key set
				record_key.#setter#(record_rec.#recordGetter#().#getter#());
#! get main multi 3

				for (#multiName# record_Readkey : #daoName#.getPrimaryKeys(record_key)) {
					#multiName# record_ReadRec  = #daoName#.get(record_Readkey);
					if(record_ReadRec != null){
						record_rec.#multiRecordGetter#().add(record_ReadRec);
					}
				}
			}
#! get end
			commitDaoTransaction();

			#loggerComment#logger.info("get 結果 = " + (record_rec == null ? "0" : "1"));
			return record_rec;

		} finally {
			closeDaoTransaction();
		}
	}

#! get PrimaryKeys start
	/**
	 * 指定されたkeyRecord内の有効な（nullでない）主キーを検索条件とし#nameJp#を<BR>
	 * 検索し主キーのみ格納されてレコードの一覧を取得する
	 *
	 * @param keyRecord
	 *            #nameJp#主キーレコード
	 * @return 取得された#nameJp#（主キーのみ格納）のリスト
	 * @throws SQLException
	 */
	public List<#voName#> getPrimaryKeys( #voName# record_keyRecord) throws SQLException {

		final List<#voName#> list_record = new LinkedList<#voName#>();
		try {

			// DAOまたはモデル作成
#! get PrimaryKeys dao model Dao
			#daoClassName# #daoName# = new #daoClassName#(getDaoTransaction());
#! get PrimaryKeys dao model Model
			#daoClassName# #daoName# = #daoClassName#.getInstance(getDaoTransaction());
#! get PrimaryKeys start 2

			// 主キーテーブル検索
			List<#voPrimaryName#> list_key = #daoName#.getPrimaryKeys(record_keyRecord.#recordGetter#());

			commitDaoTransaction();

			for (#voPrimaryName# record_rec : list_key) {
				#voName# record_new = new #voName#();
				record_new.#recordSetter#(record_rec);
				list_record.add(record_new);
			}
			list_key.clear();
			list_key = null;

			return list_record;

		} finally {
			closeDaoTransaction();
		}
	}

#! common

	// 以下 モデル共通処理	/////////////////////////////////////////////////////

	/**
	 * 新たなトランザクションを使用するこのクラスのインスタンスを取得する。<br>
	 * もし、同じパッケージ内に#className#Exクラスが存在したら、そのインスタンスを戻す。
	 *
	 * @return	#className#クラスのインスタンス、または#className#Exクラスのインスタンス
	 */
	public static #className# getInstance() {
		try {
			#className# object = (#className#) myClass.newInstance();
			object.outerTransactionFlag = false;

			return object;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 指定された外部トランザクションを使用するこのクラスのインスタンスを取得する。<br>
	 * もし、同じパッケージ内に#className#Exクラスが存在したら、そのインスタンスを戻す。
	 *
	 * @return	#className#クラスのインスタンス、または#className#Exクラスのインスタンス
	 */
	public static #className# getInstance(DaoTransaction daoTransaction) {
		try {
			#className# object = (#className#) myClass.newInstance();
			object.outerTransactionFlag = true;
			object.daoTransaction = daoTransaction;

			return object;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * DAO用トランザクションの取得
	 *
	 * @return DAO用トランザクション
	 */
	protected DaoTransaction getDaoTransaction() {

		if (!outerTransactionFlag) {
			if (daoTransaction == null) {
				daoTransaction = new DaoTransaction();
			}
		}
		return daoTransaction;
	}

	/**
	 * DAO用トランザクションのコミット<BR>
	 * 外部トランザクション不使用時にトランザクションをコミットする
	 *
	 * @throws SQLException
	 */
	protected void commitDaoTransaction() throws SQLException {
		if (!outerTransactionFlag) {
			if (daoTransaction != null) {
				daoTransaction.commit();
			}
		}
	}

	/**
	 * DAO用トランザクションのクローズ 外部トランザクション不使用時にトランザクションをクローズする
	 *
	 * @throws SQLException
	 */
	protected void closeDaoTransaction() throws SQLException {
		if (!outerTransactionFlag) {
			if (daoTransaction != null) {
				daoTransaction.close();
				daoTransaction = null;
			}
		}
	}

}
