3.1. 事前準備¶
本項では、intra-mart Accel Kaiden!でプログラミングする際の準備内容を説明します。本書では、本項の事前準備が完了していることを前提に記載しています。
3.1.1. 開発環境構築¶
本書のプログラミング方法は、intra-mart e Builder for Accel Platformを前提としています。本項では、intra-mart e Builder for Accel Platformのインストール、および開発プロジェクトの準備を行います。
3.1.1.1. intra-mart e Builder for Accel Platformの準備¶
intra-mart e Builder for Accel Platformのインストール、およびデバッグサーバの構築を行います。構築手順の詳細は、『intra-mart e Builder for Accel Platform セットアップガイド』を参照してください。コラム
デバッグサーバの構築時(WARファイルの作成時)には、利用するintra-mart Accel Kaiden!のモジュールを追加してください。また、WARファイルのデプロイ後、テナント環境の構築まで完了させてください。
3.1.1.2. モジュール・プロジェクトの作成¶
intra-mart e Builder for Accel Platform上にモジュール・プロジェクトを作成し、プロジェクトの設定を行います。プロジェクトの作成・設定の方法に関しては、『intra-mart e Builder for Accel Platform ユーザ操作ガイド』のモジュール・プロジェクト作成、およびプロジェクトの設定を参照してください。コラム
モジュール・プロジェクト作成ウィザードでは次の情報を参考に入力してください。あくまで参考値ですので、別の値を入力していただいても問題ありません。
- プロジェクト名 :tutorial
- グループID :jp.co.slcs.kaiden2
- アーティファクトID:tutorial
- バージョン :1.0.0
3.1.1.3. convention.diconの設定¶
モジュール・プロジェクトの作成後、convention.dicon でルートパッケージの設定をします。SAStruts フレームワークでは、ルートパッケージを設定することで、「ルートパッケージ.action」パッケージに配置されたJavaクラスにアクセスすることができます。コラム
例ルートパッケージを「jp.co.xxx.yyy」と設定した場合に、Javaクラス「jp.co.xxx.yyy.action.foo.BarAction」にアクセスするためのURLは「http://ホスト名/war名/foo/bar/」となります。「convention.dicon」を「src/main/resource」に配置し、「addRootPackageName」を追加します。本項以降のチュートリアルでは、ルートパッケージを”jp.co.slcs.kaiden2.tutorial.feature”と設定したものとして記載しています。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <component class="jp.co.intra_mart.framework.extension.seasar.convention.IMNamingConventionImpl"> <initMethod name="addRootPackageName"> <arg>"org.seasar.framework.container.warmdeploy"</arg> </initMethod> <initMethod name="addRootPackageName"> <arg>"jp.co.slcs.kaiden2.tutorial.feature"</arg> </initMethod> </component> <component class="org.seasar.framework.convention.impl.PersistenceConventionImpl"/> </components>コラム
convention.diconなどの各種設定を行うdiconファイルの仕様に関しては、seasar2のホームページを参照してください。
3.1.1.4. kaiden_tutorial.diconの作成¶
チュートリアルで使用する「kaiden_tutorial.dicon」を作成します。「kaiden_tutorial.dicon」を「src/main/resource」に作成し、次の様に編集します。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <!-- manager --> <!-- helper --> <!-- validator --> <!-- service --> </components>
3.1.1.5. kaiden.diconの編集¶
「kaiden_tutorial.dicon」を作成後、「kaiden.dicon」に設定を追加します。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components xmlns:xi="http://www.w3.org/2001/XInclude"> <include path="s2jdbc.dicon"/> <component name="kaidenSqlLogRegistry" class="org.seasar.extension.jdbc.SqlLogRegistry">@org.seasar.extension.jdbc.SqlLogRegistryLocator@getInstance()</component> <xi:include href="/kaiden_base.dicon" /> <xi:include href="/kaiden_extension_imw.dicon" /> <xi:include href="/kaiden_product_workflow.dicon" /> <xi:include href="/kaiden_product_labormgr.dicon" /> <!-- ↓を追加します --> <xi:include href="/kaiden_tutorial.dicon" /> <!-- ↑を追加します --> </components>コラム
環境構築時に「kaiden.dicon」以外を利用している場合は、利用したdiconファイルに設定を追加してください。設定するdiconファイルの設定は『intra-mart Accel Kaiden! セットアップガイド』のSAStruts用設定ファイルを参照してください。
intra-mart Accel Kaiden! Core Moduleのみを利用する場合→ kaiden_framework.diconを編集します。 intra-mart Accel Kaiden! 経費旅費を利用する場合→ kaiden_workflow.diconを編集します。 intra-mart Accel Kaiden! 勤務管理を利用する場合→ kaiden_labormgr.diconを編集します。 intra-mart Accel Kaiden!の全てのモジュールを利用する場合→ kaiden.diconを編集します。
3.1.2. S2JDBC¶
intra-mart Accel Kaiden!のデータベースプログラミング方法は、S2JDBCを前提としています。本項では、S2JDBCのエンティティやサービスクラスを自動生成するS2JDBC-Genの準備を行います。
3.1.2.1. S2JDBC-Genのセットアップ¶
S2JDBC-Genのダウンロード、およびセットアップを行います。セットアップの詳細はSeasarプロジェクトのサイト(http://s2container.seasar.org/2.4/ja/s2jdbc_gen/)を参照してください。
エンティティintra-mart Accel Kaiden!が使用するエンティティは、S2JDBC-Genを使ってデータベース上のテーブル定義から自動生成します。自動生成時にエンティティのスーパークラスに「jp.co.slcs.kaiden2.base.foundation.model.entity.GenerateEntity」を指定してください。注意
エンティティを自動生成する際には、必ずスーパークラス「GenerateEntity」を指定する必要がありますが、自動生成時に「GenerateEntity」がない場合、ビルドエラーが発生する場合があります。次項の「GenerateEntity」をS2JDBC-Genのプロジェクト内に配置し、エンティティの自動生成を行うようにしてください。コラム
intra-mart Accel Kaiden!のエンティティはOracle Database上のテーブルから自動生成しています。本書でも、エンティティを自動生成する際のデータベースは、Oracle Databaseを推奨します。自動生成されるエンティティのプロパティの型は、各データベースのデータ型により生成される内容が変わります。詳細はSeasarプロジェクトのサイトのデータベースのデータ型とJavaの型の対応表(http://s2container.seasar.org/2.4/ja/s2jdbc_gen/tasks/gen_entity.html)を参照してください。 サービスエンティティに対する操作を格納するクラスをサービスと呼びます。intra-mart Accel Kaiden!が使用するサービスは、S2JDBC-Genを使ってエンティティから自動生成します。自動生成時後にサービスのスーパークラスを「jp.co.slcs.kaiden2.base.foundation.model.service.GenerateService」に変更してください。コラム
サービス生成時に「GenerateService」を自動設定する場合は、S2JDBC-Genのカスタマイズが必要です。サービス生成時に抽象サービスクラスが出力される場合がありますが、スーパークラスを「GenerateService」にする場合は生成された抽象サービスクラスは不要です。
3.1.2.2. 補足¶
S2JDBC-Genプロジェクトへ配置するソースや設定ファイルは次の項を参照してください。src └─main └─java └─jp └─co └─slcs └─kaiden2 └─base └─foundation └─model ├─annotation │ AutoTimestamp.java │ AutoUpdateUser.java ├─entity │ GenerateEntity.java └─service GenerateService.java
3.1.2.2.1. GenerateEntity¶
Pathsrc/main/java/jp/co/slcs/kaiden2/base/foundation/model/entity/GenerateEntity.javapackage jp.co.slcs.kaiden2.base.foundation.model.entity; import java.sql.Timestamp; import javax.persistence.Column; import javax.persistence.MappedSuperclass; import javax.persistence.Version; import jp.co.slcs.kaiden2.base.foundation.model.annotation.AutoTimestamp; import jp.co.slcs.kaiden2.base.foundation.model.annotation.AutoUpdateUser; /** * s2jdbc-genを利用して自動生成したEntityのスーパークラス. * * @author Sumitomo Life Information Systems Co.,Ltd. */ @MappedSuperclass public abstract class GenerateEntity { /** 登録日時. */ @AutoTimestamp(insert = true, update = false) @Column(name = "entry_ts", columnDefinition = "timestamp(6)", nullable = false, unique = false) public Timestamp entryTs; /** 登録者コード. */ @AutoUpdateUser(insert = true, update = false) @Column(name = "entry_user_cd", columnDefinition = "varchar2(100)", nullable = false, unique = false) public String entryUserCd; /** 更新カウンタ. */ @Version @Column(name = "renew_cnt", columnDefinition = "number(18,0)", nullable = false, unique = false) public Long renewCnt; /** 更新日時. */ @AutoTimestamp(insert = true, update = true) @Column(name = "renew_ts", columnDefinition = "timestamp(6)", nullable = false, unique = false) public Timestamp renewTs; /** 更新者コード. */ @AutoUpdateUser(insert = true, update = true) @Column(name = "renew_user_cd", columnDefinition = "varchar2(100)", nullable = false, unique = false) public String renewUserCd; }
3.1.2.2.2. GenerateService¶
Pathsrc/main/java/jp/co/slcs/kaiden2/base/foundation/model/service/GenerateService.javapackage jp.co.slcs.kaiden2.base.foundation.model.service; import org.seasar.extension.jdbc.AutoSelect; import org.seasar.extension.jdbc.DbmsDialect; import org.seasar.extension.jdbc.IterationCallback; import org.seasar.extension.jdbc.IterationContext; import org.seasar.extension.jdbc.JdbcManager; import org.seasar.extension.jdbc.OrderByItem; import org.seasar.extension.jdbc.SqlFileSelect; import org.seasar.extension.jdbc.SqlFileUpdate; import org.seasar.extension.jdbc.SqlLogRegistry; import org.seasar.extension.jdbc.manager.JdbcManagerImpl; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; import org.seasar.extension.jdbc.operation.Operations; import org.seasar.extension.jdbc.service.S2AbstractService; import org.seasar.extension.jdbc.util.LikeUtil; import org.seasar.extension.jdbc.where.SimpleWhere; import org.seasar.extension.sql.Node; import org.seasar.extension.sql.SqlParser; import org.seasar.extension.sql.node.BindVariableNode; import org.seasar.extension.sql.node.EmbeddedValueNode; import org.seasar.extension.sql.node.ParenBindVariableNode; import org.seasar.extension.sql.parser.SqlParserImpl; import org.seasar.util.beans.util.BeanMap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.persistence.Id; import jp.co.slcs.kaiden2.base.foundation.conf.OrderType; import jp.co.slcs.kaiden2.base.foundation.exception.KaidenIllegalParametersException; import jp.co.slcs.kaiden2.base.foundation.exception.KaidenRuntimeException; import jp.co.slcs.kaiden2.base.foundation.model.conf.EntityCommonFieldNames; import jp.co.slcs.kaiden2.base.foundation.model.dto.OrderDto; import jp.co.slcs.kaiden2.base.foundation.model.entity.GenerateEntity; import jp.co.slcs.kaiden2.base.foundation.model.util.AutoFieldSetter; import jp.co.slcs.kaiden2.base.foundation.util.BeanUtil; import jp.co.slcs.kaiden2.base.foundation.util.CollectionUtil; import jp.co.slcs.kaiden2.base.foundation.util.StringUtil; import jp.co.slcs.kaiden2.base.foundation.util.log.KaidenLogger; /** * s2jdbc-genを利用して自動生成したServiceのスーパークラス. * <p> * 当クラスで実行されたSQL文はすべてログファイルにレベルDebugで出力されます。<br> * </p> * * @author Sumitomo Life Information Systems Co.,Ltd. * @param <ENTITY> エンティティの型 */ public abstract class GenerateService<ENTITY> extends S2AbstractService<ENTITY> { /** SQLファイル読込時に使用する文字エンコーディング. */ private static final String SQL_READ_CHARSET_STR = "UTF-8"; /** * ログリポジトリ. */ @Resource public SqlLogRegistry kaidenSqlLogRegistry; /** * {@inheritDoc} */ @Override protected final void setEntityClass(Class<ENTITY> entityClass) { super.setEntityClass(entityClass); super.sqlFilePathPrefix = "META-INF/sql/" + StringUtil.replace(this.getClass().getName(), ".", "/") + "/"; } /** * エンティティのクラスを返却. * * @return エンティティクラス */ public Class<ENTITY> getEntityClass() { return super.entityClass; } /** * エンティティにフィールドが含まれるかを判定. * * @param fieldName フィールド名 * @return 判定結果 true:含まれる、false:含まれない */ public boolean hasField(String fieldName) { return BeanUtil.hasField(entityClass, fieldName); } /** * PKフィールドを返却. * * @return PKフィールド */ public List<String> getPkFiled() { List<String> result = new ArrayList<String>(); Field[] fields = entityClass.getFields(); for (Field fld : fields) { Id id = fld.getAnnotation(Id.class); if (id != null) { result.add(fld.getName()); } } return result; } /** * dtoから主キー条件のkey-value(MAP)を返却. * <p> * すべてイコール条件になります。主キー項目がDTOに存在しない、または主キー条件がnull(空文字)の場合は、RuntimeExceptionをスローします。 * </p> * * @param dto 対象dto * @return 主キーのkey-value(MAP) */ public Map<String, Object> getPkCriteria(Object dto) { Map<String, Object> params = new HashMap<String, Object>(); Field[] fields = entityClass.getFields(); for (Field fld : fields) { Id id = fld.getAnnotation(Id.class); if (id != null) { try { Field dtoField = BeanUtil.getField(dto, fld.getName()); if (dtoField == null) { throw KaidenIllegalParametersException.makeInstance(); } // フィールドの値 Object value = dtoField.get(dto); if (value instanceof String && StringUtil.isEmpty((String) value)) { throw KaidenIllegalParametersException.makeInstance(); } else if (value == null) { throw KaidenIllegalParametersException.makeInstance(); } params.put(fld.getName(), value); } catch (IllegalArgumentException e) { throw KaidenRuntimeException.makeInstance(e); } catch (IllegalAccessException e) { throw KaidenRuntimeException.makeInstance(e); } catch (SecurityException e) { throw KaidenRuntimeException.makeInstance(e); } } } return params; } /** * dtoから検索条件のkey-value(MAP)を返却. * <p> * エンティティのフィールドと名称のフィールドのみ条件が作成されます。 <br /> * すべてイコール条件になります。条件値がnull(空文字)の場合は、無視されます。 * </p> * * @param dto 対象dto * @return 検索条件のMap */ public Map<String, Object> getCriteria(Object dto) { Map<String, Object> params = new HashMap<String, Object>(); Field[] fields = entityClass.getFields(); for (Field fld : fields) { Field dtoField; try { dtoField = BeanUtil.getField(dto, fld.getName()); if (dtoField != null) { // フィールドの値 Object value = dtoField.get(dto); if (value != null) { params.put(fld.getName(), value); } } } catch (SecurityException e) { throw KaidenRuntimeException.makeInstance(e); } catch (IllegalArgumentException e) { throw KaidenRuntimeException.makeInstance(e); } catch (IllegalAccessException e) { throw KaidenRuntimeException.makeInstance(e); } } return params; } /** * ORDER BYをAutoSelectで利用できる形式で作成. * * @param order ORDER BY条件 * @return ORDER BY */ private OrderByItem[] makeOrderBy(List<OrderDto> order) { List<OrderByItem> rv = new ArrayList<OrderByItem>(); for (OrderDto that : order) { if (that.orderType == OrderType.ASC) { rv.add(Operations.asc(that.fieldName)); } else { rv.add(Operations.desc(that.fieldName)); } } return rv.toArray(new OrderByItem[rv.size()]); } /** * ORDER BYをSqlFileSelectで利用できる形式で作成. * * @param order ORDER BY条件 * @return ORDER BY */ private String makeOrderByString(List<OrderDto> order) { List<String> rv = new ArrayList<String>(); for (OrderDto that : order) { if (that.orderType == OrderType.ASC) { rv.add(Operations.asc(StringUtil.camelToSnake(that.fieldName)).getCriteria()); } else { rv.add(Operations.desc(StringUtil.camelToSnake(that.fieldName)).getCriteria()); } } if (rv.size() > 0) { return StringUtil.join(rv.toArray(new String[rv.size()]), ","); } return null; } /** * generalSelect用のAtutoSelectを返却. * * @param criteria 検索条件 * @param order ORDER BY * @return AtutoSelect */ public AutoSelect<ENTITY> getAutoSelect(Map<String, Object> criteria, List<OrderDto> order) { AutoSelect<ENTITY> autoSelect = select().where(criteria); OrderByItem[] orderby = makeOrderBy(order); if (orderby.length > 0) { autoSelect = autoSelect.orderBy(orderby); } return autoSelect; } /** * 汎用検索. * * @param criteria 検索条件 * @return 検索結果 */ public List<ENTITY> genericSelectList(Map<String, Object> criteria) { return genericSelectList(criteria, new ArrayList<OrderDto>()); } /** * 汎用検索. * * @param criteria 検索条件 * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectList(Map<String, Object> criteria, List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(criteria, order).getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * 汎用検索(ロック). * * @param criteria 検索条件 * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectList4Update(Map<String, Object> criteria, List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(criteria, order).forUpdate().getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * generalSelect用のAtutoSelectを返却. * * @param where 検索条件 * @param order ORDER BY * @return AtutoSelect */ private AutoSelect<ENTITY> getAutoSelect(SimpleWhere where, List<OrderDto> order) { AutoSelect<ENTITY> autoSelect = select().where(where); OrderByItem[] orderby = makeOrderBy(order); if (orderby.length > 0) { autoSelect = autoSelect.orderBy(orderby); } return autoSelect; } /** * 汎用検索. * * @param where 検索条件 * @return 検索結果 */ public List<ENTITY> genericSelectList(SimpleWhere where) { return genericSelectList(where, new ArrayList<OrderDto>()); } /** * 汎用検索. * * @param where 検索条件 * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectList(SimpleWhere where, List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(where, order).getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * 汎用検索(ロック). * * @param where 検索条件 * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectList4Update(SimpleWhere where, List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(where, order).forUpdate().getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * generalSelectAll用のAtutoSelectを返却. * * @param order ORDER BY * @return AtutoSelect */ private AutoSelect<ENTITY> getAutoSelect(List<OrderDto> order) { AutoSelect<ENTITY> autoSelect = select(); OrderByItem[] orderby = makeOrderBy(order); if (orderby.length > 0) { autoSelect = autoSelect.orderBy(orderby); } return autoSelect; } /** * 汎用検索(全検索). * * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectAll(List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(order).getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * 汎用検索(全検索)(ロック). * * @param order ORDER BY * @return 検索結果 */ public List<ENTITY> genericSelectAll4Update(List<OrderDto> order) { List<ENTITY> ret = getAutoSelect(order).forUpdate().getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * SQLファイルを利用して検索条件から、limitとoffsetを除外. * <p> * S2JDBCにてlimitやoffsetは予約であり、SQL検索条件にあると自動的にlimitやoffsetを利用してページングをするため、意図しないページングが行われないよう無害化します * </p> * * @param criteria 検索条件 * @return 無害化した検索条件 */ private Map<String, Object> sanitizeCriteria4SqlFile(Map<String, Object> criteria) { if (criteria != null) { if (criteria.containsKey("limit")) { criteria.remove("limit"); } if (criteria.containsKey("offset")) { criteria.remove("offset"); } } return criteria; } /** * SqlFileSelectを返却. * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @param resultClass 検索結果のクラス * @param order ORDER BY * @param <T> 検索結果のクラス * @return SqlFileSelect */ public <T> SqlFileSelect<T> getSqlFileSelect(Class<T> resultClass, String sqlfile, Map<String, Object> criteria, List<OrderDto> order) { String orderby = makeOrderByString(order); if (StringUtil.isNotEmpty(orderby)) { criteria.put("orderBy", orderby); } Map<String, String> args = getSqlArguments("/" + super.sqlFilePathPrefix + sqlfile); for (Map.Entry<String, String> e : args.entrySet()) { if (!criteria.containsKey(e.getKey())) { criteria.put(e.getKey(), null); } } return selectBySqlFile(resultClass, sqlfile, sanitizeCriteria4SqlFile(criteria)); } /** * SQLファイルを解析し、SQLファイルで指定されている変数(検索条件)を返却. * * @param sqlPath SQLファイル * @return 引数リスト(valueにはnullが設定されています。キーのみ利用してください) */ private Map<String, String> getSqlArguments(String sqlPath) { StringBuffer sql = new StringBuffer(); String sqlPathDialect = null; if (super.jdbcManager instanceof JdbcManagerImplementor) { DbmsDialect dialect = ((JdbcManagerImplementor) super.jdbcManager).getDialect(); if ((StringUtil.isNotEmpty(sqlPath)) && (dialect != null) && (StringUtil.isNotEmpty(dialect.getName()))) { int posDot = sqlPath.lastIndexOf("."); if (posDot > 0) { sqlPathDialect = sqlPath.substring(0, posDot) + "_" + dialect.getName() + sqlPath.substring(posDot); } else { sqlPathDialect = sqlPath + "_" + dialect.getName(); } } } URL sqlFile = null; if (StringUtil.isNotEmpty(sqlPathDialect)) { sqlFile = GenerateService.class.getResource(sqlPathDialect); } if (null == sqlFile) { sqlFile = GenerateService.class.getResource(sqlPath); } InputStream is = null; BufferedReader br = null; try { is = sqlFile.openStream(); br = new BufferedReader(new InputStreamReader(is, SQL_READ_CHARSET_STR)); while (br.ready()) { sql.append(br.readLine()); } } catch (IOException e) { throw KaidenRuntimeException.makeInstance(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { throw KaidenRuntimeException.makeInstance(e); } } if (is != null) { try { is.close(); } catch (IOException e) { throw KaidenRuntimeException.makeInstance(e); } } } Map<String, String> argMap = new HashMap<String, String>(); SqlParser parser = new SqlParserImpl(sql.toString()); Node sqlNode = parser.parse(); sqlNodeParse(sqlNode, argMap); return argMap; } /** * SQLを解析する. * * @param node SQL解析Node * @param argMap 変数MAP ※当メソッド内で追加します。 */ private void sqlNodeParse(Node node, Map<String, String> argMap) { if (BindVariableNode.class.isInstance(node)) { argMap.put(((BindVariableNode) node).getExpression(), null); } else if (ParenBindVariableNode.class.isInstance(node)) { argMap.put(((ParenBindVariableNode) node).getExpression(), null); } else if (EmbeddedValueNode.class.isInstance(node)) { argMap.put(((EmbeddedValueNode) node).getExpression(), null); } for (int i = 0; i < node.getChildSize(); i++) { sqlNodeParse(node.getChild(i), argMap); } } /** * SQLファイル検索. * <p> * Like条件の%等はエスケープされます * </p> * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @param resultClass 検索結果のクラス * @param order ORDER BY * @param <T> 検索結果のクラス * @return 検索結果 */ public <T> List<T> selectBySql(Class<T> resultClass, String sqlfile, Map<String, Object> criteria, List<OrderDto> order) { List<T> ret = getSqlFileSelect(resultClass, sqlfile, criteria, order).getResultList(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * SQLファイル検索. * <p> * Like条件の%等はエスケープされます * </p> * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @return 検索結果 */ public List<BeanMap> selectBySql(String sqlfile, Map<String, Object> criteria) { return selectBySql(BeanMap.class, sqlfile, criteria, new ArrayList<OrderDto>()); } /** * SQLファイル検索. * <p> * Like条件の%等はエスケープされます * </p> * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @param order ORDER BY * @return 検索結果 */ public List<BeanMap> selectBySql(String sqlfile, Map<String, Object> criteria, List<OrderDto> order) { return selectBySql(BeanMap.class, sqlfile, criteria, order); } /** * SQLファイル検索後、Filterクラスによって内容をフィルタリングし返却. * <p> * 引数「limit」が0より大きい場合は以下のように動作します。 * <p> * <ul> * <li>返却データは「limit」の数までです</li> * <li>「numberOfPage」が指定されている場合にはそのページ番号のデータのみを返却します。</li> * </ul> * * @param sqlfile sqlファイル名 * @param criteria SQL検索条件 ※Like条件の%等はエスケープされます * @param resultClass 検索結果のクラス * @param order ORDER BY * @param filterClasses フィルタリングクラス * @param limit フィルタリング結果の返却最大数 * @param numberOfPage フィルタリング結果の返却ページ * @param <T> 検索結果(リスト)のクラス * @return 検索結果 */ @SuppressWarnings("unchecked") public <T> Map<String, Object> selectBySqlFilter(Class<T> resultClass, String sqlfile, Map<String, Object> criteria, List<OrderDto> order, SqlResultFilterIF[] filterClasses, long limit, long numberOfPage) { if (criteria.containsKey("limit")) { criteria.remove("limit"); } numberOfPage = numberOfPage <= 1 ? 1L : numberOfPage; FilterIterationCallBack filterIterationCallBack = new FilterIterationCallBack(filterClasses, limit, numberOfPage); Map<String, Object> ret = getSqlFileSelect(resultClass, sqlfile, criteria, order).iterate( (IterationCallback<T, Map<String, Object>>) filterIterationCallBack); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 // 結果なし if (ret == null) { return this.getSelectBySqlFilterNoDataResult(); } if (limit > 0) { Long matchCount = (Long) ret.get("matchCount"); long pageTtl = (matchCount / limit) + ((matchCount % limit) > 0 ? 1 : 0); if (matchCount >= (limit * (numberOfPage - 1) + 1)) { // 指定ページが存在する ret.put("resultPage", numberOfPage); } else { // 指定ページが存在しないため、最大ページ番号で再検索 FilterIterationCallBack reFilterIterationCallBack = new FilterIterationCallBack(filterClasses, limit, pageTtl); ret = getSqlFileSelect(resultClass, sqlfile, criteria, order).iterate( (IterationCallback<T, Map<String, Object>>) reFilterIterationCallBack); ret.put("resultPage", Long.valueOf(pageTtl)); } matchCount = (Long) ret.get("matchCount"); pageTtl = (matchCount / limit) + ((matchCount % limit) > 0 ? 1 : 0); // 返却ページ総数の計算 if (ret.get("matchCount") != null) { ret.put("resultPageTotal", Long.valueOf(pageTtl)); } } else { // limitが0以下なら全件返却のため、総ページ数、ページ番号とも1を返却 ret.put("resultPageTotal", Long.valueOf(1L)); ret.put("resultPage", Long.valueOf(1L)); } return ret; } /** * SQLファイル検索後、Filterクラスによって内容をフィルタリングし返却. * <p> * {@link #selectBySqlFilter(Class, String, Map, List, SqlResultFilterIF[], long, long)} * と同様の機能で、戻り値を特定のDTOでなくBeanMapで返却します。 * </p> * * @param sqlfile sqlファイル名 * @param criteria SQL検索条件 ※Like条件の%等はエスケープされます * @param order ORDER BY * @param filterClasses フィルタリングクラス * @param limit フィルタリング結果の返却最大数 * @param numberOfPage フィルタリング結果の返却ページ * @param <T> 検索結果(リスト)のクラス * @return 検索結果 * @return */ public <T> Map<String, Object> selectBySqlFilter(String sqlfile, Map<String, Object> criteria, List<OrderDto> order, SqlResultFilterIF[] filterClasses, long limit, long numberOfPage) { return selectBySqlFilter(BeanMap.class, sqlfile, criteria, order, filterClasses, limit, numberOfPage); } /** * 検索後、Filterクラスによって内容をフィルタリングし返却. * * @param resultClass 検索結果のクラス * @param criteria SQL検索条件 ※Like条件の%等はエスケープされます * @param order ORDER BY * @param filterClasses フィルタリングクラス * @param limit フィルタリング結果の返却最大数 * @param numberOfPage フィルタリング結果の返却ページ * @param <T> 検索結果(リスト)のクラス * @return 検索結果 */ @SuppressWarnings("unchecked") public <T> Map<String, Object> selectListByFilter(Class<T> resultClass, Map<String, Object> criteria, List<OrderDto> order, SqlResultFilterIF[] filterClasses, long limit, long numberOfPage) { if (criteria.containsKey("limit")) { criteria.remove("limit"); } numberOfPage = numberOfPage <= 1 ? 1L : numberOfPage; FilterIterationCallBack filterIterationCallBack = new FilterIterationCallBack(filterClasses, limit, numberOfPage); Map<String, Object> ret = getAutoSelect(criteria, order).iterate( (IterationCallback<ENTITY, Map<String, Object>>) filterIterationCallBack); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 // 結果なし if (ret == null) { return this.getSelectBySqlFilterNoDataResult(); } if (limit > 0) { Long matchCount = (Long) ret.get("matchCount"); long pageTtl = (matchCount / limit) + ((matchCount % limit) > 0 ? 1 : 0); if (matchCount >= (limit * (numberOfPage - 1) + 1)) { // 指定ページが存在する ret.put("resultPage", numberOfPage); } else { // 指定ページが存在しないため、最大ページ番号で再検索 FilterIterationCallBack reFilterIterationCallBack = new FilterIterationCallBack(filterClasses, limit, pageTtl); ret = getAutoSelect(criteria, order).iterate( (IterationCallback<ENTITY, Map<String, Object>>) reFilterIterationCallBack); ret.put("resultPage", Long.valueOf(pageTtl)); } matchCount = (Long) ret.get("matchCount"); pageTtl = (matchCount / limit) + ((matchCount % limit) > 0 ? 1 : 0); // 返却ページ総数の計算 if (ret.get("matchCount") != null) { ret.put("resultPageTotal", Long.valueOf(pageTtl)); } } else { // limitが0以下なら全件返却のため、総ページ数、ページ番号とも1を返却 ret.put("resultPageTotal", Long.valueOf(1L)); ret.put("resultPage", Long.valueOf(1L)); } List<ENTITY> resultList = (List<ENTITY>) ret.get("resultList"); if (CollectionUtil.isNotEmpty(resultList)) { ret.put("resultList", CollectionUtil.changeDtoListClass(resultClass, resultList)); } return ret; } /** * 検索条件で、Like検索のワイルドカードをエスケープします. * <p> * % → $% * </p> * * @param criteria 検索条件 * @param likeTarget LIKE検索対象カラム */ public void escapeWildcard(Map<String, Object> criteria, String[] likeTarget) { if (likeTarget == null || likeTarget.length == 0) { return; } for (String that : likeTarget) { if (criteria.containsKey(that)) { Object value = criteria.get(that); if (value instanceof String) { criteria.put(that, LikeUtil.escapeWildcard((String) value)); } } } } /** * {@inheritDoc} * <p> * {@link AutoFieldSetter#autoTimestampByUpdate(Object)}、 {@link AutoFieldSetter#autoUpdateuserByUpdate(Object)} * を実行後に、<code>super.update(entity)</code>を実行します * </p> */ @Override public int update(ENTITY entity) { AutoFieldSetter.autoTimestampByUpdate(entity); AutoFieldSetter.autoUpdateuserByUpdate(entity); int ret = super.update(entity); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * エンティティを更新. * <p> * 指定のプロパティを更新対象から除外します。<br> * {@link AutoFieldSetter#autoTimestampByUpdate(Object)}、 {@link AutoFieldSetter#autoUpdateuserByUpdate(Object)} * を実行後に、 <br> * <code>super.jdbcManager.update(entity).excludes(propertyNames).execute()</code>を実行します * </p> * * @param entity 更新対象エンティティ * @param propertyNames 更新対象から除外するプロパティ名の配列 * @return 更新件数 */ public int updateExcludes(ENTITY entity, String[] propertyNames) { AutoFieldSetter.autoTimestampByUpdate(entity); AutoFieldSetter.autoUpdateuserByUpdate(entity); int ret = super.jdbcManager.update(entity).excludes(this.adjustExcludesPropertyNames(propertyNames)).execute(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * エンティティを更新. * <p> * 指定のプロパティのみを更新対象とします。<br> * {@link AutoFieldSetter#autoTimestampByUpdate(Object)}、 {@link AutoFieldSetter#autoUpdateuserByUpdate(Object)} * を実行後に、 <br> * <code>super.jdbcManager.update(entity).excludes(propertyNames).execute()</code>を実行します * </p> * * @param entity 更新対象エンティティ * @param propertyNames 更新対象とするプロパティ名の配列 * @return 更新件数 */ public int updateIncludes(ENTITY entity, String[] propertyNames) { AutoFieldSetter.autoTimestampByUpdate(entity); AutoFieldSetter.autoUpdateuserByUpdate(entity); int ret = super.jdbcManager.update(entity).includes(adjustInludesPropertyNames(propertyNames)).execute(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * {@inheritDoc} * <p> * {@link AutoFieldSetter#autoTimestampByInsert(Object)}、 {@link AutoFieldSetter#autoUpdateuserByInsert(Object)} * を実行後に、<code>super.insert(entity)</code>を実行します * </p> */ @Override public int insert(ENTITY entity) { AutoFieldSetter.autoTimestampByInsert(entity); AutoFieldSetter.autoUpdateuserByInsert(entity); int ret = super.insert(entity); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * 一括挿入. * * @param dataList 挿入対象リスト * @return 挿入件数の配列 ※S2AbstractService#insert(ENTITY)の仕様に準じる */ public int[] insertBatch(List<ENTITY> dataList) { List<Integer> rvList = new ArrayList<Integer>(); for (ENTITY entity : dataList) { rvList.add(this.insert(entity)); } return CollectionUtil.toIntArray(rvList); } /** * 一括更新. * <p> * 指定のプロパティを更新対象から除外します。<br> * </p> * * @param dataList 更新対象リスト * @return 更新件数(Ingeger)の配列 */ public int[] updateBatch(List<ENTITY> dataList) { List<Integer> rvList = new ArrayList<Integer>(); for (ENTITY entity : dataList) { rvList.add(this.update(entity)); } return CollectionUtil.toIntArray(rvList); } /** * 一括更新. * <p> * 指定のプロパティのみを更新対象とします。<br> * </p> * * @param dataList 更新対象リスト * @param propertyNames 更新対象から除外するプロパティ名の配列 * @return 更新件数(Ingeger)の配列 */ public int[] updateExcludesBatch(List<ENTITY> dataList, String[] propertyNames) { List<Integer> rvList = new ArrayList<Integer>(); for (ENTITY entity : dataList) { rvList.add(this.updateExcludes(entity, propertyNames)); } return CollectionUtil.toIntArray(rvList); } /** * 一括更新. * * @param dataList 更新対象リスト * @param propertyNames 更新対象とするプロパティ名の配列 * @return 更新件数(Ingeger)の配列 */ public int[] updateIncludesBatch(List<ENTITY> dataList, String[] propertyNames) { List<Integer> rvList = new ArrayList<Integer>(); for (ENTITY entity : dataList) { rvList.add(this.updateIncludes(entity, propertyNames)); } return CollectionUtil.toIntArray(rvList); } /** * 一括削除. * * @param dataList 更新対象リスト * @return 削除数(Ingeger)の配列 */ public int[] deleteBatch(List<ENTITY> dataList) { List<Integer> rvList = new ArrayList<Integer>(); for (ENTITY entity : dataList) { rvList.add(delete(entity)); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 } return CollectionUtil.toIntArray(rvList); } /** * 内容に応じて挿入/更新を切り替えて実行. * <p> * エンティティのrenewCntがnullの場合はinsert、そうでない場合はupdateを行います * </p> * * @param data 更新対象 * @return 挿入/更新件数. */ public int autoInsUpd(ENTITY data) { if (((GenerateEntity) data).renewCnt == null) { return this.insert(data); } else { return this.update(data); } } /** * 内容に応じて挿入/更新を一括実行. * <p> * エンティティのrenewCntがnullの場合はinsert、そうでない場合はupdateを行います * </p> * <p> * エラーが発生した場合はnullを返却 * </p> * * @param dataList 更新対象リスト * @return 挿入/更新件数. */ public int[] autoInsUpdBatch(List<ENTITY> dataList) { List<Integer> rvList = new ArrayList<Integer>(); genericLock(dataList); for (ENTITY data : dataList) { rvList.add(this.autoInsUpd(data)); } return CollectionUtil.toIntArray(rvList); } /** * 汎用ロック. * <p> * 注意!引数のリストを主キーの昇順にソートしますので、注意してください * </p> * * @param dataList 対象エンティティのリスト */ public void genericLock(List<ENTITY> dataList) { // PKでソート List<String> pk = this.getPkFiled(); List<OrderDto> order = new ArrayList<OrderDto>(); for (String fld : pk) { OrderDto that = new OrderDto(); that.fieldName = fld; that.orderType = OrderType.ASC; order.add(that); } CollectionUtil.dtoSort(dataList, order); // PKキー順にロック for (ENTITY that : dataList) { this.genericSelectList4Update(getPkCriteria(that), new ArrayList<OrderDto>()); } } /** * 主キーの昇順でソート定義を生成. * * @return ソート定義(主キーの昇順) */ public List<OrderDto> makeOrderListFromPk() { List<String> pk = this.getPkFiled(); List<OrderDto> order = new ArrayList<OrderDto>(); for (String fld : pk) { OrderDto that = new OrderDto(); that.fieldName = fld; that.orderType = OrderType.ASC; order.add(that); } return order; } /** * getSelectBySqlFilter時の返却値なしの状態のMapを返却. * <p> * 主にSQL実行前に戻り値を返却する場合に利用してください * </p> * * @return 返却値なしの状態のMap */ public Map<String, Object> getSelectBySqlFilterNoDataResult() { Map<String, Object> result = new HashMap<String, Object>(); result.put("resultList", new ArrayList<Object>()); // フィルター結果(データ) ※最大でもlimit数まで result.put("matchCount", Long.valueOf(0L)); // フィルターにマッチした数 ※limit以上もカウント result.put("sqlTotal", Long.valueOf(0L)); // フィルター前のカウント result.put("resultPageTotal", Long.valueOf(0L)); // 返却ページtotal result.put("resultPage", Long.valueOf(0L)); // 返却ページ番号 return result; } /** * selectListFilter用コールバック. * <p> * 返却値(MAP)には以下の情報が格納されています。 * <table border="1"> * <tr> * <th>key</th> * <th>value</th> * </tr> * <tr> * <td>reusltList</td> * <td>List<Object> フィルター結果(指定ページのデータのみ)</td> * </tr> * <tr> * <td>matchCount</td> * <td>Long フィルター一致数</td> * </tr> * <tr> * <td>sqlTotal</td> * <td>Long SQLヒット数</td> * </tr> * <tr> * <td>resultPageTotal</td> * <td>Long 返却ページ総数</td> * </tr> * <tr> * <td>resultPage</td> * <td>Long 返却ページ番号</td> * </tr> * </table> * * @author Sumitomo Life Information Systems Co.,Ltd. */ private class FilterIterationCallBack implements IterationCallback<Object, Map<String, Object>> { /** フィルタークラス. */ private final SqlResultFilterIF[] filters; /** 返却結果の最大数. */ private final long limit; /** 返却ページ番号. */ private final long numberOfPage; /** 戻り値. */ private final Map<String, Object> result = new HashMap<String, Object>(); /** * コンストラクタ. * * @param filters フィルタークラス配列 * @param limit 返却最大件数 * @param numberOfPage 返却ページ番号 */ public FilterIterationCallBack(SqlResultFilterIF[] filters, long limit, long numberOfPage) { this.filters = filters; this.limit = limit; this.numberOfPage = numberOfPage <= 1 ? Long.valueOf(1L) : numberOfPage; // 戻り値の準備 result.put("resultList", new ArrayList<Object>()); // フィルター結果(データ) ※最大でもlimit数まで result.put("matchCount", Long.valueOf(0L)); // フィルターにマッチした数 ※limit以上もカウント result.put("sqlTotal", Long.valueOf(0L)); // フィルター前のカウント result.put("resultPageTotal", Long.valueOf(0L)); // 返却ページtotal result.put("resultPage", Long.valueOf(0L)); // 返却ページ番号 } /** * {@inheritDoc} */ @Override public Map<String, Object> iterate(Object selectEntity, IterationContext ctx) { boolean match = true; for (SqlResultFilterIF sqlFilter : this.filters) { match = sqlFilter.filter(selectEntity) && match; if (!match) { break; } } // インクリメント this.result.put("sqlTotal", ((Long) this.result.get("sqlTotal")) + 1); if (match) { Long matchCount = ((Long) this.result.get("matchCount")) + 1; this.result.put("matchCount", (matchCount)); if (limit <= 0 || (matchCount <= (limit * numberOfPage) && matchCount >= (limit * (numberOfPage - 1) + 1))) { @SuppressWarnings("unchecked") List<Object> lst = (List<Object>) this.result.get("resultList"); lst.add(selectEntity); } } return this.result; } } /** * 更新除外対象プロパティ配列補正. * <p> * 更新除外対象プロパティ配列に下記プロパティを含む場合、当該要素を削除します。 * </p> * <li>{@link EntityCommonFieldNames.RENEW_USER_CD 更新者コード}</li> <br> * <li>{@link EntityCommonFieldNames.TS 更新日時}</li> * * @param arg 更新除外対象プロパティ * @return 補正後プロパティ配列 */ private String[] adjustExcludesPropertyNames(String[] arg) { List<String> list = new ArrayList<String>(Arrays.asList(arg)); int targetIdx = list.lastIndexOf(EntityCommonFieldNames.RENEW_USER_CD); if (targetIdx != -1) { list.remove(targetIdx); } targetIdx = list.lastIndexOf(EntityCommonFieldNames.RENEW_TS); if (targetIdx != -1) { list.remove(targetIdx); } return list.toArray(new String[list.size()]); } /** * 更新対象プロパティ配列補正. * <p> * 更新対象プロパティ配列に下記プロパティを含まない場合、当該要素を追加します。 * </p> * <li>{@link EntityCommonFieldNames.RENEW_USER_CD 更新者コード}</li> <br> * <li>{@link EntityCommonFieldNames.TS 更新日時}</li> * * @param arg 更新対象プロパティ * @return 補正後プロパティ配列 */ private String[] adjustInludesPropertyNames(String[] arg) { List<String> list = new ArrayList<String>(Arrays.asList(arg)); int targetIdx = list.lastIndexOf(EntityCommonFieldNames.RENEW_USER_CD); if (targetIdx == -1) { list.add(EntityCommonFieldNames.RENEW_USER_CD); } targetIdx = list.lastIndexOf(EntityCommonFieldNames.RENEW_TS); if (targetIdx == -1) { list.add(EntityCommonFieldNames.RENEW_TS); } return list.toArray(new String[list.size()]); } /** * SQLフィイル更新. * * @param sqlfile sqlファイル名 * @return 更新件数 */ public int updateBySql(String sqlfile) { return updateBySql(sqlfile, null); } /** * SQLフィイル更新. * * @param sqlfile sqlファイル名 * @param criteria 更新条件 * @return 更新件数 */ public int updateBySql(String sqlfile, Map<String, Object> criteria) { int ret = getSqlFileUpdate(sqlfile, criteria).execute(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * SqlFileUpdateを返却. * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @return SqlFileUpdate */ public SqlFileUpdate getSqlFileUpdate(String sqlfile, Map<String, Object> criteria) { Map<String, String> args = getSqlArguments("/" + super.sqlFilePathPrefix + sqlfile); for (Map.Entry<String, String> e : args.entrySet()) { if (!criteria.containsKey(e.getKey())) { criteria.put(e.getKey(), null); } } return updateBySqlFile(sqlfile, criteria); } /** * 汎用検索結果件数取得. * * @return 検索結果件数 */ @Override public long getCount() { return getCount(new HashMap<String, Object>()); } /** * 汎用検索結果件数取得. * * @param criteria 検索条件 * @return 検索結果件数 */ public long getCount(Map<String, Object> criteria) { long ret = select().where(criteria).getCount(); KaidenLogger.debug(kaidenSqlLogRegistry.getLast().getCompleteSql()); // SQL文をログに出力 return ret; } /** * Sqlファイルの検索結果件数を返却. * * @param sqlfile sqlファイル名 * @return Sqlファイルの検索結果件数 * @see #getCountBySql(String, Map) */ public long getCountBySql(String sqlfile) { return getCountBySql(sqlfile, null); } /** * Sqlファイルの検索結果件数を返却. * * @param sqlfile sqlファイル名 * @param criteria 検索条件 * @return Sqlファイルの検索結果件数 */ public long getCountBySql(String sqlfile, Map<String, Object> criteria) { if (null == criteria || criteria.isEmpty()) { return jdbcManager.getCountBySqlFile(sqlFilePathPrefix + sqlfile); } Map<String, String> args = getSqlArguments("/" + super.sqlFilePathPrefix + sqlfile); for (Map.Entry<String, String> e : args.entrySet()) { if (!criteria.containsKey(e.getKey())) { criteria.put(e.getKey(), null); } } return jdbcManager.getCountBySqlFile(sqlFilePathPrefix + sqlfile, criteria); } /** * JdbcManagerを設定. * * @param jdbcManager JdbcManager */ public void setJdbcManager(JdbcManager jdbcManager) { this.jdbcManager = jdbcManager; // @formatter:off KaidenLogger.info(getClass().getSimpleName() + "に jdbcManagerが設定されました。[" + ((JdbcManagerImpl) jdbcManager).getDialect().getName() + "]"); // @formatter:on } }
3.1.2.2.3. AutoTimestamp¶
Pathsrc/main/java/jp/co/slcs/kaiden2/base/foundation/model/annotation/AutoTimestamp.javapackage jp.co.slcs.kaiden2.base.foundation.model.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import jp.co.slcs.kaiden2.base.foundation.model.service.GenerateService; /** * 自動現在時刻設定. * <p> * S2JDBCのエンティティにアノテーションを付与することで、insert時/update時に自動的に現在日付時刻を設定します。<br > * ただし自動的に設定されるのは、{@link GenerateService}の{@link GenerateService#insert(Object) insert}/ * {@link GenerateService#update(Object) update}を利用した場合のみです。 * <p> * * @author Sumitomo Life Information Systems Co.,Ltd. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface AutoTimestamp { /** insert時に現在日付時刻を設定. */ boolean insert(); /** update時に現在日付時刻を設定. */ boolean update(); }
3.1.2.2.4. AutoUpdateUser¶
Pathsrc/main/java/jp/co/slcs/kaiden2/base/foundation/model/annotation/AutoUpdateUser.javapackage jp.co.slcs.kaiden2.base.foundation.model.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import jp.co.slcs.kaiden2.base.foundation.model.service.GenerateService; /** * 自動ログインユーザ設定. * <p> * S2JDBCのエンティティにアノテーションを付与することで、insert時/update時に自動的にログインユーザを設定します。<br > * ただし自動的に設定されるのは、{@link GenerateService}の{@link GenerateService#insert(Object) insert}/ * {@link GenerateService#update(Object) update}を利用した場合のみです。 * <p> * * @author Sumitomo Life Information Systems Co.,Ltd. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface AutoUpdateUser { /** insert時にログインユーザを設定. */ boolean insert(); /** update時にログインユーザを設定. */ boolean update(); }
3.1.2.2.5. s2jdbc-gen-build.xml/s2jdbc-gen-build.properties¶
次ファイルは参考としてお使いください。ご利用中の環境によっては、動作しない場合がありますので、ご注意ください。s2jdbc-gen-build.xml
<project name="example-s2jdbc-gen" default="generate-src" basedir="."> <property file="s2jdbc-gen-build.properties" /> <path id="classpath"> <pathelement location="${classpathdir}"/> <pathelement location="${resourcesdir}"/> <fileset dir="${librarydir}"/> </path> <taskdef resource="s2jdbc-gen-task.properties" classpathref="classpath"/> <property name="templateFilePrimaryDir" value="resources/tempaltes"/> <property name="pluralFormFile" value="${templateFilePrimaryDir}/plural.properties"/> <target name="generate-src"> <gen-entity tableNamePattern="${tableNamePattern}" ignoreTableNamePattern="${ignoreTableNamePattern}" entitySuperclassName="jp.co.slcs.kaiden2.base.foundation.model.entity.GenerateEntity" pluralFormFile="${pluralFormFile}" useTemporalType="false" useAccessor="false" applyDbCommentToJava="true" showTableName="true" showColumnName="true" showColumnDefinition="true" showJoinColumn="true" rootPackageName="${rootPackageName}" entityPackageName="entity" templateFilePrimaryDir="${templateFilePrimaryDir}" overwrite="true" classpathref="classpath" /> <javac srcdir="${srcdir}" destdir="${classpathdir}" encoding="UTF-8" fork="true" debug="on" includeantruntime="" classpathref="classpath" /> <gen-names classpathDir="${classpathdir}" rootPackageName="${rootPackageName}" namesPackageName="entity" templateFilePrimaryDir="${templateFilePrimaryDir}" generateNamesAggregateClass="false" overwrite="true" classpathref="classpath" /> <gen-service classpathDir="${classpathdir}" rootPackageName="${rootPackageName}" servicePackageName="service" templateFilePrimaryDir="${templateFilePrimaryDir}" overwrite="true" classpathref="classpath" /> <gen-condition classpathDir="${classpathdir}" rootPackageName="${rootPackageName}" conditionPackageName="service" templateFilePrimaryDir="${templateFilePrimaryDir}" overwrite="true" classpathref="classpath" /> <javac srcdir="${srcdir}" destdir="${classpathdir}" encoding="UTF-8" fork="true" debug="on" includeantruntime="" classpathref="classpath" /> </target> </project>
- s2jdbc-gen-build.properties
# classpath srcdir=src/main/java classpathdir=target/classes resourcesdir=resources librarydir=lib # 対象とするテーブル名の正規表現です。 # (デフォルト値:「".*"」) tableNamePattern=.* # 対象としないテーブル名の正規表現です。 # (デフォルト値:「"(SCHEMA_INFO|.*\$.*)"」) ignoreTableNamePattern= # ルートパッケージ名です。 # エンティティクラスは、ルートパッケージ名と「entity」をピリオドで連結したパッケージに配置します。 # 名前クラスは、ルートパッケージ名と「entity」をピリオドで連結したパッケージに配置します。 # サービスクラスは、ルートパッケージ名と「service」をピリオドで連結したパッケージに配置します。 # 条件クラスは、ルートパッケージ名と「service」をピリオドで連結したパッケージに配置します。 rootPackageName=aaa.bbb.ccc.foundation.model