データ管理

1. データ管理について

リレーショナルデータベース(RDB)などに代表されるデータの構造定義や永続化を実現する仕組みとして、 iPLAssではEntityメタデータを利用します。 RDBにおけるテーブルはEntityとして定義し、テーブルのカラムはPropertyとして定義します。

Entityには以下の機能・特徴があります。

  • 動的な定義
    Entityは管理画面上から動的に作成することができます。 RDBのように物理的にテーブルを追加・修正する必要はありません。 またEntityに定義可能なPropertyにはタイプ(StringやInteger、Binaryなど)ごとに 特化したProperty型があらかじめ用意されています。 格納したいデータタイプに合わせてProperty型を選択していきます。

  • データ操作画面の自動生成(Generic Entity Manager)
    Entityを定義するだけで、汎用的な検索画面、登録・編集画面が実行可能になります。 汎用画面は、表示項目や表示レイアウトなど、独自にカスタマイズすることもできます。また、カレンダービュー、ツリービューなどいくつかの表示形式を標準で提供しています。
    詳細はGEM(Generic Entity Manager)を参照してください。
    また、 モバイルファーストなデータ操作画面(Mobile Design Components、通称:MDC) を提供します。
    詳細はMDC(Mobile Design Components) を参照してください。

  • データ検証
    Propertyごとに必須チェックやLengthチェックなどのValidatorを設定することができます。

  • EventListener
    EntityのCRUD操作(登録、参照、更新、削除など)時の前後に独自処理を組み込むことができます。

  • データのバージョン管理
    Entityの1レコードに対して、複数のバージョンを保持することができます。 バージョン管理を利用することで、修正履歴を保持できたり、先日付データを事前に登録することが可能になります。

  • Entityの権限制御
    EntityのCRUD操作(登録、参照、更新、削除など)に対する権限をロールを利用して制御することができます。
    詳細は認可を参照してください。

  • クエリ言語(EQL)
    データ操作はiPLAss独自のEQLというSQLライクなクエリ言語を利用します。 Entityデータの永続化にはバックエンドでRDBを利用しますが、 開発者はバックエンドのRDB差異を意識する必要はほとんどありません。
    詳細はEQLリファレンスを参照してください。

  • WebApi操作
    EntityのCRUD操作(登録、参照、更新、削除など)を実行するWebApiを標準で提供しています。
    詳細はEntityCRUD APIを参照してください。

  • 全文検索
    Entityデータに対して、全文検索エンジンを利用したIndexの生成、検索機能を標準でサポートしています。
    詳細は全文検索を参照してください。

  • データ監査ログ
    EntityのCRUD操作(登録、参照、更新、削除など)に対するログを記録することができます。 記録されたログはデータ操作画面上で表示したり、管理コンソール上で参照することができます。

  • データ暗号化
    Entityのデータ内容をデータベースに保存する際に暗号化することができます。 データベースの暗号化オプションを利用可能な場合は、そちらを利用することを推奨しますが、 データベースの暗号化オプションの利用が難しい場合の次善のソリューションとして利用可能です。

2. Entity

2.1. Entityの作成

Entityアイコンを右クリックして「Entityを作成する」を選択してください。

階層化(フォルダのようにグループ化)する場合はドット(.)区切りで指定してください。 他のメタデータは基本的にスラッシュ(/)で階層化しますが、Entityは特別です。
Entityを作成したタイミングで、メニューアイテムが作成されます。 またテナントに標準で作成されている DEFAULT メニュー定義がある場合は、 最後にアイテムが追加されます。

2.2. 共通Property

Entityにはあらかじめ標準PropertyとシステムPropertyが定義されています。

あらかじめ定義されているPropertyは変更や削除することはできません。
共通のPropertyとして利用されている名前は予約語です。Entity内で同じ名前のPropertyを定義することはできません。

標準Property

レコードのキーに該当するIDやレコードの内容を表すPropertyが定義されています。

名前 表示名 データ型 内容

oid

オブジェクトID

String

レコードを一意に特定するID。変更不可。

name

名前

String

レコードを表すラベル。必須項目。値はユニークである必要はありません。

description

説明

String

レコードの説明。任意項目。

オブジェクトID (oid)

Entityデータは1レコード単位に oid という一意のKEY値を保持します。

標準の動作として、oid はEntityデータの登録時に自動的に採番されます。 更新処理で変更することはできません。 後述するEntityどうしの参照定義(Reference Property)においても、 この oid で参照関係を保持します(正確には oid + version です)。

entity property oid
一意となる範囲

標準で自動採番される oid 値は、Entity単位で一意となる値です。 テナント単位で一意な値ではないので、 oid からEntityを特定することはできません。

名前 (name)

name はレコードに対するラベルを想定しています。
name は必須項目ですが値の変更は可能です。また値として一意である必要もありません。

説明 (description)

description はレコードに対する説明を想定しています。
description はString型の任意項目なので、利用可否も含め自由に利用してください。

システムProperty

データのバージョン制御のためのPropertyや、データ操作時の情報を保持するPropertyが定義されています。 システムPropertyは自由に値を設定することはできません。データ操作時に自動で制御されます。

名前 表示名 データ型 内容

version

バージョン

Integer

データのバージョン管理 で利用。管理しない場合は0。

state

ステータス

Select

バージョン管理用。

startDate

有効開始日

DateTime

バージョン管理用。

endDate

有効終了日

DateTime

バージョン管理用。

createDate

作成日

DateTime

データ作成日時。

updateDate

更新日

DateTime

データ更新日時。

createBy

作成者

String

データ作成者。作成者に該当する User Entityの oid が格納される。

updateBy

更新者

String

データ更新者。更新者に該当する User Entityの oid が格納される。

lockedBy

ロックユーザー

String

データロック機能用。ロック者に該当する User Entityの oid が格納される。

システムPropertyの注意点

システムPropertyは制御用としてiPLAss内部で制御されるため、 各アプリケーションで独自の用途として値を格納したりしないでください。 バージョンアップなどで増減したり、格納される値が変更される可能性があります。

startDateendDate についても、「ユーザー」「おしらせ情報」Entityなどで一部利用していますが、 Entityの バージョン管理設定 により利用される可能性があるため、基本的には利用できません。

2.3. Propertyの設定

Entityに対して、保存したいデータ項目に合わせたPropertyを追加していきます。
Entityに対するより高度な設定については 高度な設定 で説明します。

Propertyの作成

Propertyを作る際は、格納する値の型に特化したデータ型の選択や、必須項目や長さなどの制約条件の設定を行います。

Propertyを追加する場合は Add ボタン、編集する場合は対象のPropertyレコードをダブルクリック、 削除する場合は対象のPropertyを選択(ShiftやCtrlで複数可)して Remove ボタンをクリックします。 またPropertyの順番を並び替える場合はドラッグ&ドロップで並び替えてください。

Propertyの詳細設定

Propertyは次の項目を設定可能です。 また指定したPropertyのデータ型によって、設定する項目が変更されます (一部データ型により変更できない項目があります)。

設定項目 設定内容

Name

物理名を指定します。英数字のみ指定可能です。

Display Name

表示名を指定します。
未指定の場合、Entity定義の保存時にNameが設定されます。

Type

データ型を指定します。

Multiple

多重度を指定します。

Required

必須項目かを指定します。
必須項目にした場合、検証ロジック(Validator)に NotNull が追加されます。

CanEdit

値を変更できるかを指定します。
Entityデータの更新時(update)の変更チェックや、汎用画面上での編集可否に利用されます。

Index Type

インデックスを指定します。

Encrypt Mode

暗号化有無、および形式を指定します。

Validator

検証ロジックを指定します。

Normalizer

正規化ロジックを指定します。

データ型の指定

提供されているPropertyのデータ型です。基本的な型とiPLAssに特化した特殊な型があります。

基本型
説明 Java型

String

文字列型です。
文字数に関する制約があります。

String

Boolean

真・偽を表す型です。

Boolean

Integer

整数を表す数値型です。

Long

Float

小数を表す数値型です。

Double

Decimal

正確な小数計算を扱う数値型です。
少数桁数と丸めモードが指定可能です。

MySQLで小数点第5位以下を使用する場合は、MySQLのシステム変数 div_precision_increment を設定してください。 DIV演算子を使用しない場合でも、iPLAss内部で桁数調整のため自動的にDIVをしているので div_precision_increment の設定が必要です。

BigDecimal

DateTime

日付と時間を表す型です。

java.sql.Timestamp

Date

日付を表す型です。

java.sql.Date

Time

時間を表す型です。

java.sql.Time

特殊型(拡張型)
説明 Java型

Select

選択値として「値とラベル」のセットを定義することができる型です。

org.iplass.mtp.entity.SelectValue

AutoNumber

自動採番値を扱う型です。

String

Expression

式を設定することができる型です。

String

Binary

バイナリデータを扱う型です。(BLOB型)

org.iplass.mtp.entity.BinaryReference

LongText

String型では入りきらない文字列を扱う型です。(BLOB型)

String

Reference

各エンティティを関連付ける事ができる型です。

org.iplass.mtp.entity.Entity

Java型はCommandやUtilityClass、TemplateなどでEntityデータを扱う際のデータ型です。

それぞれのデータ型の詳細は、データ型 を参照してください。

多重度について

Entityには1つのPropertyに対して複数の値を保持することが可能となっています(配列イメージ)。

oid name col1(multiple=5) ref1(multiple=*)

1

data1

[a,b,c,d,e]

[{oid=1,ver=0},{oid=2,ver=0},{oid=3,ver=0}]

2

data2

[a,b,c]

[]

3

data3

[]

[{oid=1,ver=0},{oid=2,ver=0}]

  • Reference 型については、無制限を表す「*」を指定できます。

  • Reference 型以外のPropertyは数値のみ指定できます。

Reference 型以外で多数の多重度を持たせたい場合は、パフォーマンスを考慮して、 別Entityを定義して Reference 型で参照するようにするか、 独自の Storage Space を利用することを検討してください。

Property変更時の注意点

Entity の Property 定義を変更する際は、次の点に注意してください。

Property追加・削除時

基本的にデータの更新・ロックは発生しません。
ただし、プロパティ追加に伴ってページの追加が必要になった場合は、データに対してレコードロックが掛ります。

Property更新時
  • データ型を変更した場合(データの変換が可能な場合)

    • データの値は引き継がれます。ただし、データに対してレコードロックが掛ります。

  • データ型を変更した場合(データの変換が不可能な場合)

    • データの値は引き継がれません。このため基本的にはデータに対してロックは掛りません。
      ただし、新しいデータ型に合わせて新しくカラムが割り当てられるため、この結果としてページの追加が必要になった場合は、レコードロックが掛ります。

  • Index定義を変更した場合

    • データに対してレコードロックが掛ります。

プロパティ型の変更によるデータの引き継ぎ
  • 相互変換可能

    プロパティ型 補足

    DECIMAL ⇔ INTEGER ⇔ FLOAT

    桁数に応じての四捨五入等は発生

    DATE ⇔ DATETIME

    時間部分は00:00:00で補完

    TIME ⇔ DATETIME

    日付部分は1970-01-01で補完

    AUTONUMBER ⇔ STRING

  • 一方向のみ変換可能

    プロパティ型 補足

    * ⇒ STRING

    LONGTEXT,BINARY除くすべての型はSTRINGに変換可能

    STRING ⇒ LONGTEXT

    STRING型にて格納されている文字列のうち、DBのVARCHARカラムのバイト数-21バイト以上の文字は切り捨てされる。
    Oracleの場合3979byte以上の文字は切り捨てされる

    BOOLEAN ⇒ SELECT

    SELECT型の値としては、false→0、true→1になる

2.4. 高度な設定

Entityに対して提供されているその他の機能について説明します。

設定項目 設定内容

共通Propertyの変更

oidname Propertyをカスタマイズします。

Versioning

Entityデータのバージョン管理方式を指定します。

Storage Space

Entityデータの格納先を指定します。

save audit log

EntityデータのCRUD操作に対するログを記録するかを指定します。

crawl for full text search

全文検索機能用のINDEXを作成するかを指定します。

cache query result

Entityの検索結果をキャッシュするかを指定します。

Mapping Class

CommandなどでEntity操作を行う際に、Javaで実装されたEntityクラスを利用する場合に指定します。

EventListener

EntityのEventListenerを指定します。

Data Localization

Entityデータの国際化対応を指定します。

共通Propertyの変更

oidname については他のPropertyを指定することで代用することができます。

oid Propertyの変更

外部システムからのデータ取り込みや、IDとしてユーザーにわかりやすい値にしたい場合など、 oid として利用するPropertyを変更することが可能です。

Admin Consoleで oid を指定する場合は、「OID」列で指定してください。

entity property oid custom
指定可能なProperty属性

以下の属性のPropertyのみ oid として指定することが可能です。

  • 型が 基本型 または AutoNumber である

  • 必須項目である

  • 変更不可である

  • 多重度が1である

複合指定

複数のPropertyを指定することが可能です。 この場合、 oid に格納される値は、選択したPropertyを上から順番にハイフン「-」で 結合した値になります。

登録済データに対する注意点

既に登録済みのEntityデータが存在する状態で oid Propertyを変更した場合、 登録済みのデータは自動的には変更されません。 このような場合は、Entityデータのエクスポート/インポートなどによりデータを手動で変更する必要があります。

name Propertyの変更

oid 同様、 name も対象とするPropertyを変更することが可能です。

Admin Consoleで変更する場合は、「Name」列で指定してください。

指定可能なProperty属性

以下の属性のPropertyのみ name として指定することが可能です。

複合指定

oid と異なり、複数のPropertyを指定することはできません。

「name」を指定した場合の注意点

name を指定した場合には、以下の点について考慮する必要があります。

  • 登録時の動作
    name Propertyを独自に設定した場合、Entityデータの更新時に name に同じ値が設定されます( name Propertyがなくなるわけではありません)。 例えば、 name Propertyと、独自に指定したPropertyそれぞれに値を設定して更新した場合、name に設定された値は上書きされます。

  • 汎用画面(GEM)のカスタマイズが必要
    汎用画面では、標準で namedescription Propertyが検索・詳細画面上に表示されます。 name Propertyを独自に設定した場合は、name を削除し独自Propertyを追加するなど、汎用画面のレイアウト調整が必要です。

登録済データに対する注意点

既に登録済みのEntityデータが存在する状態で name Propertyを変更した場合、 登録済みのデータは自動的には変更されません。 例えば、必須ではない項目を必須に変更して name に指定した場合も、 登録済のデータは値が設定されていない可能性がある状態になってしまいます。このようなデータは最初の更新時にエラーになります。
この場合は、Entityデータのエクスポート/インポートなどにより登録済みデータを手動でメンテナンスする必要があります。

nameを利用したくない場合

作成したいEntityに name に該当するPropertyがない場合は、 AutoNumber 型のPropertyを作成して、それを name として指定してください。

データのバージョン管理

Entityの1レコードに対して、複数のバージョンを保持することができます。 バージョン管理を利用することで、修正履歴を保持できたり、先日付データを事前に登録することが可能になります。 バージョン管理する場合、Entityに定義される共通プロパティ versionstatestartDateendDate が利用され、現在有効なバージョンが決定されます。

version プロパティは排他制御のためのものではありません。排他制御は updateDate プロパティでチェックしています。
EQLでバージョン管理されたEntityを検索する際、EQLの検索条件にバージョン管理項目を指定した場合、全てのバージョンのデータを検索対象とします。未指定の場合、現在有効なバージョンのデータのみを検索対象とします。

バージョン管理方式には以下の種類があります。

タイプ 説明

NONE

バージョンデータを保持しません。データに対する最新の状態のみ保持されます。

NUMBER BASE

共通Propertyの version を利用して、複数のバージョンデータを保持します。

TIME BASE

共通Propertyの startDateendDate (有効期間)を利用して、複数のバージョンデータを保持します。

SIMPLE TIME BASE

共通Propertyの startDateendDate (有効期間)を利用して、複数のバージョンデータを保持します。SIMPLE TIME BASEでは、複数バージョン間で有効期間が重なることは許可されません。

STATE BASE

共通Propertyの state を利用して、有効なバージョンを制御します。

NUMBER BASE

共通Propertyの version を複数保持することが可能になります。 検索処理で有効なデータは version が最大、且つ state有効 のものになります。

oid version state startDate endDate name 有効

1

0

有効

-

-

sample1_v0

1

1

有効

-

-

sample1_v1

*

1

2

無効

-

-

sample1_v2

TIME BASE

共通Propertyの startDateendDate (有効期間)を複数保持することが可能になります。 データを更新する際に有効期間を指定します。 検索処理で有効なデータは システム日時で有効期間に該当(startDate≦システム日時<endDate)し、且つ version が最大、且つ state有効 のものになります。

例1(システム日時が20021/03/29 12:00:00)
oid version state startDate endDate name 有効

1

0

有効

2018/04/01 00:00:00

2030/04/01 00:00:00

sample1_v0

1

1

有効

2019/04/01 00:00:00

2021/04/01 00:00:00

sample1_v1

*

1

2

有効

2021/04/01 00:00:00

2022/04/01 00:00:00

sample1_v2

1

3

無効

2019/04/01 00:00:00

2025/04/01 00:00:00

sample1_v3

例2(システム日時が20021/04/01 00:00:00)
oid version state startDate endDate name 有効

1

0

有効

2018/04/01 00:00:00

2030/04/01 00:00:00

sample1_v0

1

1

有効

2019/04/01 00:00:00

2021/04/01 00:00:00

sample1_v1

1

2

有効

2021/04/01 00:00:00

2022/04/01 00:00:00

sample1_v2

*

1

3

無効

2019/04/01 00:00:00

2025/04/01 00:00:00

sample1_v3

データ登録時に有効期間が未指定の場合は、自動的に「システム日時」~「2099/12/31 00:00:00」が設定されます。 また TIME BASE の場合も version はカウントアップされます。 システム日時に対して有効なデータ期間が複数存在する場合は、 version が大きい、且つ state有効 なバージョンが有効なデータとなります。

SIMPLE TIME BASE

共通Propertyの startDateendDate (有効期間)で有効なバージョンを制御します。SIMPLE TIME BASEは、TIME BASEとは異なり、複数バージョン間で有効期間が重なることは許可されません。 検索処理で有効なデータは システム日時で有効期間に該当(startDate≦システム日時<endDate)し、且つ state有効 のものになります。

例(システム日時が20021/03/29 12:00:00)
oid version state startDate endDate name 有効

1

0

有効

2018/04/01 00:00:00

2019/04/01 00:00:00

sample1_v0

1

1

有効

2019/04/01 00:00:00

2021/04/01 00:00:00

sample1_v1

*

1

2

有効

2021/04/01 00:00:00

2022/04/01 00:00:00

sample1_v2

1

3

無効

2023/04/01 00:00:00

2024/04/01 00:00:00

sample1_v3

データ登録時に有効期間が未指定の場合は、自動的に「システム日時」~「2099/12/31 00:00:00」が設定されます。 また TIME BASE の場合も version はカウントアップされます。 データ更新時、state有効 であり、且つ有効期間が重複するバージョンを登録しようとした場合はエラーとなり登録できません。

STATE BASE

共通Propertyの state を利用し、現在有効なバージョンを制御します。 state が有効なバージョンは最大でも1つとなります。 検索処理で有効なデータは state有効 のものになります。

oid version state startDate endDate name 有効

1

0

無効

-

-

sample1_v0

1

1

有効

-

-

sample1_v1

*

1

2

無効

-

-

sample1_v2

また STATE BASE の場合も version はカウントアップされます。 データ更新時、state有効 のバージョンを登録しようとした場合、他のバージョンの state の値は 無効 に変更されます。

バージョンデータの更新方法

新しいバージョンのデータを作成する場合は、明示的に更新する必要があります。 普通に更新した場合は新しいバージョンデータは作成されず、対象バージョンのデータが更新されます。

汎用画面からデータを登録する場合は、詳細画面に 新しいバージョンとして更新 というボタンが表示されるので、 そこから更新を行います。

Commandなど独自で更新処理を実装する場合は UpdateOption で設定します。

import org.iplass.mtp.entity.EntityValidationException;
import org.iplass.mtp.entity.UpdateOption;
import org.iplass.mtp.entity.TargetVersion;

EntityManager em = ManagerLocator.manager(EntityManager.class);

try {
    //別バージョンで更新する場合、UpdateOptionに対して、
    //TargetVersion.NEWを指定すると新しいバージョンとして保存される
    //通常のupdate処理は「TargetVersion.CURRENT_VALID」(有効バージョン)
    UpdateOption option = new UpdateOption();
    option.setTargetVersion(TargetVersion.NEW);

    em.update(entity, option);
} catch (EntityValidationException e) {
}
ReferencePropertyが参照するバージョン

Entity間の連携を定義するためのReference型のPropertyが参照する参照先のバージョンは、 ReferencePropertyで指定した「バージョン管理」設定によって決定されます。

Unique Property の制約

バージョン管理を行う場合、 Unique Index が指定されたPropertyは変更不可になります。 Entity定義の保存時に、 Unique Index が指定されているPropertyは canEdit = false として保存されます。

Storage Spaceの変更

全てのEntityのデータは、標準の設定ではバックエンドのRDB上で1つの物理テーブルに格納されます。

例えば、

  • 一部のデータを暗号化したいため当該Entityを格納するテーブルのテーブルスペースを分けたい

  • あるEntityは大量件数が想定されるため、他のデータとは物理的に別テーブルで管理し、他のEntityへのパフォーマンス面での悪影響を抑えたい

といった要件を実現すため、Entityデータを格納する領域をEntity単位で指定することが可能です。 この領域のことをiPLAssでは Storage Space と呼称します。

ただしこの機能を利用するには、通常意識しないバックエンドDB上に物理テーブルを作成し、service-configにStorageSpace定義が必要となります。

詳細は Storage Space を参照してください。

データ操作ログの記録

EntityデータのCRUD操作に対するログを記録することができます。

記録されたログは、汎用画面の操作ログSectionで表示することが可能です。 詳細は 操作ログセクションを参照してください。

また AuditLogManager を利用することでプログラム上で取得することが可能です。
詳細は AuditLogManager のJavaDocを参照してください。

/** 注意:以下はGroovy形式で書いています。 */

import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.auditlog.AuditLog;
import org.iplass.mtp.entity.auditlog.AuditLogManager;
//import org.iplass.mtp.entity.auditlog.AuditLog.Action;

AuditLogManager alm = ManagerLocator.manager(AuditLogManager.class);

String entityName = "samples.Sample";
String oid = "00001";

//ログは件数が多くなることが想定されるため、limit(-1などは不可)、offsetの指定が必要です
int limit = 100;
int offset = 0;

//trueの場合、プロパティが検索条件に指定された場合でも、CREATEに対する操作ログを併せて取得します
boolean withCreateRecord = true;

//ログの取得(可変長引数のパラメータとしてプロパティ名を検索条件に追加できます)
List<AuditLog> auditLogs = alm.getAuditLog(entityName, oid, limit, offset, withCreateRecord, "SampleProperty001", "SampleProperty002");

println("audit log size =" + auditLogs.size());

auditLogs.each{auditLog ->
    println("log id =" + auditLog.getLogId())
    println("action =" + auditLog.getAction())      //操作Action(AuditLog.Action)
    println("user id =" + auditLog.getUserId())          //操作ユーザー(oid)
    println("user name =" + auditLog.getUserName())      //操作ユーザー名
    println("property =" + auditLog.getPropertyName())    //プロパティ
    println("oldValue =" + auditLog.getOldValue())        //更新前の値
    println("newValue =" + auditLog.getNewValue())        //更新後の値

    //他の値はAuditLogのJavaDocを参照してください。
};

/* java形式
auditLogs.forEach(auditLog -> {
    System.out.println("log id =" + auditLog.getLogId());
    System.out.println("action =" + auditLog.getAction());
    ・・・・・
});
*/

Query結果のキャッシュ

検索時のQueryに対する検索結果をキャッシュすることが可能です。 実行されたQueryと同じ条件のQueryがキャッシュに存在すれば、実際の検索を実行せずにキャッシュの結果を返します。 キャッシュデータは、対象のEntityデータが1件でも更新されたタイミングでクリアされます。

Mapping Classの利用

Entityの検索処理として利用する EntityManager のload処理やQuery(EQL)を使ったsearchEntity処理の結果として、 標準では Entity インターフェースを実装した GenericEntity クラスが返ってきます。

org.iplass.mtp.entity.Entity
org.iplass.mtp.entity.GenericEntity

この GenericEntity クラスには共通Property項目に対するAccessorメソッドは提供されていますが、 各Entityで個別に追加したPropertyに対しては、 getValue("プロパティ名")setValue("プロパティ名", 値) としてデータを操作する必要があります。

そこで Entity インターフェースを実装したJavaクラスを作成し、各Entityのプロパティに対応したAccessorメソッドを定義できるようにするのが このMapping Classです。Javaクラスの名前を指定した場合、loadやsearchEntity処理の結果として、指定したJavaクラスのインスタンスが返ります。

AdminConsoleの Create Java Class を実行することで、 保存されているEntity定義に対応するJavaクラス( GenericEntity の継承クラス)のコードを生成、ダウンロードできます。

MappingするJavaクラスは、クラスパス上に配置する必要があります。

EventListener

Entityに対する操作時に独自の処理を実行したい場合、操作イベントに対してListenerを設定することができます。 ListenerはJavaClassまたはGroovyScriptとして実装することができます。

Entityのイベント

イベントは EntityManager を経由したEntity操作時に発生します。 汎用画面でのEntity操作時にも、内部的に EntityManager を利用しているためイベントが発生します。

以下に EntityManager のメソッドとイベントの関連を示します。

EntityManager#method イベント 戻り値 説明

load

onLoad

void

ロード処理。

searchEntity

onLoad

void

検索処理(Entity形式)。1件ごとに呼び出される

validate

beforeValidate

void

検証処理。

insert

beforeValidate
beforeInsert
afterInsert

void
boolean
void

登録処理。

update

beforeValidate
beforeUpdate
afterUpdate

void
boolean
void

更新処理。

delete

beforeDelete
afterDelete
afterPurge

boolean
void
void

削除処理。afterPurge は、DeleteOptionの purge=true の場合のみ実行されます。

purge

afterPurge

void

ごみ箱から、削除処理。

restore

afterRestore

void

ごみ箱から、復活処理。

searchupdateAlldeleteAll 時はイベントは発生しません。

イベントの戻り値として boolean を返すものは、 false を返すと後続の処理を実行しません。

updatedelete 時など更新前のEntityが存在する状態で、各通知メソッドが呼び出される際の引き渡されるentityインスタンスは、 EntityManagerから各更新メソッド呼び出し時のEntityインスタンスがそのまま引き渡されたものです。 そのため、oid以外のプロパティ項目を保持していない場合もあることにご注意ください。
Javaクラスによる実装

JavaクラスとしてEventListenerを実装する場合は、 EntityEventListener インターフェースを実装したクラスを作成します。

org.iplass.mtp.entity.EntityEventListener
設定
設定項目 設定内容

class name

実装したクラスを指定します。

mapped by reference info is unnecessary for listener

update 処理の場合に、beforeUpdateイベントに渡される更新前Entityをloadする際に被参照Propertyを対象にしないかを指定します(LoadOptionを制御)。 詳細は、update時の更新前Entityについて を参照してください。

(例)EntityEventListenerを利用したEntityPropertyの更新
public class UserEntityEventListener implements EntityEventListener {

    /**
     * FIRST_NAME、LAST_NAMEからNameを設定する
     */
    @Override
    public void beforeValidate(Entity entity, EntityEventContext context) {
        String firstName = entity.getValue(User.FIRST_NAME);
        String lastName = entity.getValue(User.LAST_NAME);
        String name = firstName + lastName;
        entity.setName(name);   //ユーザー名をセットする
    }

    /**
     * 更新対象項目として名前が含まれていない場合、名前を追加する
     * (validate内で手動で変更しているので)
     */
    @Override
    public boolean beforeUpdate(Entity entity, EntityEventContext context) {
        //コンテキストから更新Optionを取得
        UpdateOption uo = (UpdateOption) context.getAttribute(EntityEventContext.UPDATE_OPTION);

        //更新対象項目として名前が含まれていない場合
        if (!uo.getUpdateProperties().contains(Entity.NAME)) {
            //コンテキストから変更前のEntityを取得
            Entity before = (Entity)context.getAttribute(EntityEventContext.BEFORE_UPDATE_ENTITY);

            //名前の変更チェック
            if (!before.getName().equals(entity.getName())) {
                uo.getUpdateProperties().add(Entity.NAME);  //異なる場合は更新項目として追加する
            }
        }
        return true;
    }
}

引数で渡されるEntityEventContextについては、EntityEventContext を参照してください。

Scriptによる実装

Script(GrovyScript)でEventListenerを実装する場合は、scriptとして2種類の定義方法があります。

  • Javaと同様に、EntityEventListenerをimplementsしたクラスを記述。

  • 対象のEventを指定し、実行されるScriptを記述。

設定
設定項目 設定内容

script

実行するScriptを指定します。Javaと同様の形式で記述する場合は、 Javaクラスによる実装 を参照してください。 クラス形式を指定した場合は、選択されたEventは無視されます。

events

実行するイベントをしています。 複数指定した場合は、各イベントで同じスクリプトが実行されます。

mapped by reference info is unnecessary for listener

update 処理の場合に、beforeUpdateイベントに渡される更新前Entityをloadする際に被参照Propertyを対象にしないかを指定します(LoadOptionを制御)。 詳細は、update時の更新前Entityについて を参照してください。

利用可能な変数

利用可能なバインド変数は以下のものです。

バインド変数 設定される値

entity

対象のEntityデータ。

context

EntityEventContext

event

発生したイベント種別。 org.iplass.mtp.entity.definition.listeners.EventType

user

ユーザー情報。

date

システム日時。

event には発生したイベントのタイプが設定されています。 Script形式の場合、1つのListenerで複数のEventに対する処理を実装できるので、Eventごとに処理を分けたい場合の判断として利用します。 このような場合、EventごとにそれぞれListener定義することもできます。

(例)typeによる処理の制御方法
import org.iplass.mtp.entity.definition.listeners.EventType;

if (event == EventType.BEFORE_VALIDATE) {

    

} else if (event == EventType.BEFORE_UPDATE) {

    

    return true;
}

boolean の戻り値が必要なイベントに対して、戻り値を返していない場合は true として制御します。

EntityEventContext

更新系のイベントに対しては EntityEventContext という引数で、対象Entityに関する更新情報が渡されます。

org.iplass.mtp.entity.EntityEventContext

EntityEventContextには以下の情報が格納されています。

KEY 対象Event

VALIDATE_PROPERTIES

beforeValidate

バリデーション対象のProperty名のList(List<String>)。

  • validate時は引数で渡された validatePropertyList

  • insert時は null

  • update時はUpdateOptionの updateProperties

UPDATE_OPTION

update時

updateの引数で渡されたUpdateOption。

BEFORE_UPDATE_ENTITY

beforeUpdate

更新前のEntity(load)

DELETE_OPTION

delete時

deleteの引数で渡されたDeleteOption

KEYはEntityEventContextの変数名として定義されています。

イベント間での値の受け渡し方法

EntityEventContextはMap形式で値を保持することができるので、 イベント間で独自の値も受け渡すことができます。
EntityEventContext#getAttribute(KEY)EntityEventContext#setAttribute(KEY, value) で値を取得、設定してください。

EntityEventContextはEntityManagerのメソッド呼び出しの単位でインスタンスが生成されます。 Entityに対して複数イベントを登録している場合は、複数イベント間で共有されます。 ただし update 時に発生する beforeValidate イベントは、 beforeValidate 内のみで共有されます(後続の beforeUpdate 以降は別インスタンス)。

(例)update時のListener呼び出しイメージ
EntityManager#update()

    ////beforeValidateイベント実行
    EntityEventContext eeContext = new EntityEventContext();
    for (EntityEventListener listener: listeners) {
        listener.beforeValidate(entity, eeContext);
    }

    //validate処理実行

    //handleBeforeUpdateイベント実行
    //検証時のEntityEventContextは引き継がない
    EntityEventContext eeContext2 = new EntityEventContext();
    for (EntityEventListener listener: listeners) {
        if (!listener.handleBeforeUpdate(entity, eeContext2)) {
            return;
        }
    }

    //実際のupdate処理実行

    //handleAfterUpdateイベント実行
    for (EntityEventListener listener: listeners) {
        listener.handleAfterUpdate(entity, eeContext2);
    }
update時の更新前Entityについて

update処理時にはEntityEventContextに更新前のEntity情報がloadされてセットされます。 このload時に被参照Propertyを取得しないかを設定します。

true の場合、更新前Entityのload処理で被参照Propertyを除外します。 (load時のLoadOptionを withMappedByReference=false にして処理します)

被参照Propertyは更新対象のPropertyではないため、Listener内部の処理で参照する必要がないのであれば、除外することで処理を高速化できます。

beforeValidateを使ったバリデーションエラーの発生のさせ方
  • 例外にしたい場合は基本的にはApplicaitonExceptionをスロー
    ApplicaitonException をスローした場合、ApplicaitonException の引数に設定した例外メッセージがエラーメッセージとしてGEMやMDCの画面上に表示されます。
    以下は、ApplicaitonException をスローさせる場合のサンプルコードです。

ApplicationException
@Override
public void beforeValidate(Entity entity, EntityEventContext context) {

    // ここになんらかのチェック処理を設定

    // チェック処理の結果、例外として処理する場合
    throw new ApplicationException("画面に表示するエラーメッセージ");
}

ApplicaitonException の引数で指定したメッセージが画面上部に表示されます。

GEM画面のエラーメッセージ表示例

application exception sample gem

MDC画面のエラーメッセージ表示例

application exception sample mdc
  • 項目ごとにエラーメッセージを画面表示させたい場合はEntityValidationExceptionをスロー
    EntityValidationException をスローした場合、 第2引数に設定した項目ごとのエラーメッセージのリストがGEMやMDCの画面上に表示されます。 第2引数にはValidateError型のリストに画面に表示するエラーメッセージを項目ごとに設定します。
    以下は、EntityValidationException をスローさせる場合のサンプルコードです。

EntityValidationException
@Override
public void beforeValidate(Entity entity, EntityEventContext context) {

    // ここになんらかのチェック処理を設定

    // ValidateError型のリストを作成してエラーメッセージを設定
    List<ValidateError> validateResults = new ArrayList<ValidateError>();
    ValidateError errorMsg = new ValidateError();

    errorMsg.addErrorMessage("画面に表示する項目単位のエラーメッセージ");
    errorMsg.setPropertyName("hogehoge");  // エラーメッセージを表示する項目を設定
    validateResults.add(errorMsg);

    // チェック処理の結果、例外として処理する場合
    throw new EntityValidationException("例外メッセージ", validateResults);
}

iPLAssで定義済みのバリデーションエラーのメッセージが画面上部に表示されます。 EntityValidationException の引数で指定したエラーメッセージが項目ごとに表示されます。

GEM画面のエラーメッセージ表示例

entity validation exception sample gem

MDC画面のエラーメッセージ表示例

entity validation exception sample mdc

データの多言語化

Entityデータ自体に対する多言語設定が行えます。多言語設定は Data Localization で指定します。
詳細については、 データの多言語化を参照してください。

SendNotification

SendNotificationを利用することでEntityに対する操作時にMail/SMS/Push/Webhook通知の送信ができます。

設定
設定項目 設定内容

Notification type

送信する通知のタイプです。必須項目。

  • Mail : メール通知

  • SMS : SMS通知

  • PushNotification : Push通知

  • Webhook : Webhook通知

Template

通知のテンプレート定義。必須項目。

ResultHandlerImplClassName

(Webhookを選択した場合)
Webhookのレスポンスを処理したい場合は、Javaクラスを用意し、ここに指定してください。

  • 実装するJavaクラスは、org.iplass.mtp.webhook.WebhookResponseHandlerを継承する必要があります。詳細はJavaDocを参照してください。

Synchronous

(Webhookを選択した場合)
Webhookを同期処理とするか、非同期処理とするかを設定します。デフォルトでは非同期(チェックしない)です。

SendTogether

(Push NotificationかMailを選択した場合)
設定した宛先全てで一括送信するのか、一個づつ送信するのかを設定できます。

Destination

通知先を指定。選択したNotification typeに合わせ、通知先を設定してください。いずれの場合もGroovyTemplate形式で記述可能です。

  • Mail : メールアドレス

  • SMS : 電話暗号

  • PushNotification : Firebase Cloud Messaging(FCM) における通知先(登録トークン、通知キー、トピック、もしくは、メッセージのターゲットを決定する条件の論理先)を指定。詳細は、FCMの ドキュメントを参照してください

  • Webhook : WebhookEndpoint名

Notification condition

送信する場合の条件スクリプト 。boolean の戻り値が必要です。未設定の場合、必ず通知を送信します。

events

実行するイベントをしています。 複数指定した場合は、各イベントで同じスクリプトが実行されます。

  • トランザクションが存在する場合、コミットされた時点で通知を送信します。

  • トランザクションが存在ない場合、即時に通知を送信します。

mapped by reference info is unnecessary for listener

update 処理の場合に、beforeUpdateイベントに渡される更新前Entityをloadする際に被参照Propertyを対象にしないかを指定します(LoadOptionを制御)。 詳細は、update時の更新前Entityについて を参照してください。

条件スクリプトで利用可能な変数

利用可能なバインド変数は以下のものです。

バインド変数 設定される値

entity

対象のEntityデータ。

context

EntityEventContextを参照してください。

event

発生したイベント種別。 org.iplass.mtp.entity.definition.listeners.EventType

user

ユーザー情報。

date

システム日時。

・通知のテンプレート定義で利用可能な変数

バインド変数 設定される値

tenant

テナント情報。

entity

対象のEntityデータ。

context

EntityEventContextを参照してください。

event

発生したイベント種別。 org.iplass.mtp.entity.definition.listeners.EventType

user

ユーザー情報。

date

システム日時。

2.5. 標準提供のEntity

標準で提供されるEntityについて説明します。

標準で提供される一部のEntityにはEventListenerが組み込まれているため、 それらのEntityデータのインポート時には、Listener処理の実行有無に注意が必要となります。
Entity名 EE Only 説明 EventListenerの処理概要

mtp.Information
(お知らせ情報)

-

ニュースなどのコンテンツの情報が格納されます。

有効終了日が未設定の場合に、「2099/12/31」を設定します。

mtp.auth.ActionPermission
(Action権限)

-

Actionに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.EntityPermission
(Entity権限)

-

Entityに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.WebApiPermission
(WebApi権限)

-

WebApiに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.CubePermission
(Cube権限)

Cubeに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.WorkflowPermission
(Workflow権限)

Workflowに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.UserTaskPermission
(UserTask権限)

UserTaskに対する権限の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.Role
(ロール)

-

ロールに付与された各権限やロール割り当て条件の参照情報などを含みます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.RoleCondition
(ロール条件)

-

ロールに適用する条件の情報が格納されます。

権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.Group
(グループ情報)

-

ユーザーに設定可能なグループの情報が格納されます。親グループが指定でき、階層で表現することが可能です。

グループ情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。

mtp.auth.Rank
(ランク情報)

-

ユーザーに設定可能なランク(会員種別など)の情報が格納されます。

-

mtp.auth.User
(ユーザー情報)

-

ユーザーの情報が格納されます。姓や名などのユーザー属性に関する項目とアカウントポリシーなどの認証に関する項目を含みます。

  • ユーザーの認証に関する情報を保持する t_account テーブルとの連携を行います

  • ユーザー情報の登録・変更・削除時のバリデーションチェック(重複チェック、パスワード指定の場合のパスワードパターンチェック、管理者権限チェックなど)を行っています

  • ユーザー情報の登録・変更・削除時にユーザーに対して設定された認証ポリシーの通知処理(ユーザー登録時のメールによる仮パスワード通知など)を実行します

mtp.maintenance.MetaDataTag
(メタデータTag)

-

MetaDataExplorerを使用してインポートする際にローカルメタデータのTagの情報が一時的に格納されます。

-

mtp.maintenance.Package
(パッケージ)

-

Packaging機能で設定したPackageの情報が格納されます。

-

mtp.auth.oidc.OpenIdProviderAccount
(OpenIDプロバイダでのアカウント)

-

OpenIDプロバイダのアカウントの情報が格納されます。アカウントに紐づくiPLAssのユーザー情報を含みます。

  • 重複登録を防止するためにユニークキーを作成してEntityに設定しています。

  • アカウントに紐づくiPLAssのユーザー情報のoidをEntityに設定しています。

mtp.auth.UserImpersonationPermission
(ユーザー偽装権限)

代理ログイン機能で使用されます。権限を与えるユーザーと成り代わり可能なユーザーがセットで格納されます。

-

mtp.listing.SavedList
(保存リスト)

汎用検索や定型集計・簡易BIの検索条件やローデータが保存リストとして格納されます。

-

mtp.listing.SavedListFolder
(保存リストのフォルダ)

保存リストで設定したフォルダの情報が格納されます。

-

mtp.scheduling.ScheduledTask
(スケジュールタスク)

スケジューラ機能で使用されるスケジュールタスクの情報が格納されます。実行日時や実行結果などが含まれます。

  • 実行フラグがONの場合、スケジュールタスクを開始しています。

  • 初回起動日時が変更された場合、スケジュールタスクを再設定しています。

mtp.scheduling.ScheduledTaskHistory
(スケジュールタスク履歴)

スケジューラ機能で使用されるスケジュールタスクの履歴情報が格納されます。ScheduledTask定義で History Logging がONの場合にスケジュールタスクの実行履歴を保持します。

-

mtp.workflow.Assignment
(割当)

ユーザータスクのユーザーへの割当情報が格納されます。

  • ワークフローの委譲が行われている場合、委譲可能かをチェックしています。

  • 操作対象のユーザータスクをロックして、割当されたユーザータスクをEntityに設定しています。

mtp.workflow.UserTask
(ユーザータスク)

ユーザータスクの情報が格納されます。

  • タスクのキーを生成して、Entityに設定しています。

  • ユーザータスクのステータスが完了に更新された場合、後続のFlowの実行条件が判断されます。

mtp.workflow.UserTaskQueue
(ユーザータスクキュー)

ユーザータスクの割当ルールに ToQueue が選択された場合に使用されるユーザータスクのキュー情報が格納されます。

-

mtp.workflow.Workflow
(ワークフロー)

現在のワークフローの状態が格納されます。

-

mtp.workflow.ProcessHistory
(ワークフロー処理履歴)

ワークフローのNodeの historyLogging がtrueの場合に当該Nodeの実行結果が履歴として格納されます。

-

mtp.workflow.WorkflowTarget
(ワークフロー対象)

ワークフロー対象の情報が格納されます。

-

wam.auth.IdProviderAccount
(IDプロバイダでのアカウント)

IDプロバイダにおいて認証されたアカウント情報が格納されます。

  • 重複登録を防止するためにユニークキーを作成してEntityに設定しています。

wam.auth.UserSignUp
(UserSignUp)

ユーザーの新規登録依頼内容が一時的に格納されます。 アクティベーション処理が完了した際に、iPLAssのユーザー情報に反映されます。

-

wam.auth.VerificationRequest
(検証要求)

メール、SMSなどでユーザーの本人確認(アクティベーション)をする際に検証情報が格納されます。

-

wam.siteauth.CodeToken
(Code and Token)

WAMプラグインモジュールを経由した認証フローで使用される認可コードが一時的に格納されます。

-

3. Entity Property

データ型、Validatorについての詳細を記載します。
インデックス指定、データの暗号化については、 高度な設定で説明します。

3.1. データ型

データ型を一覧で参照したい場合は、 データ型の指定 を参照してください。

基本型の注意点

String型の文字数制約

String型はバックエンドとして利用するRDBの定義によって、格納できる最大文字数が制限されます。 標準の設定の場合、Oracleは varchar2(4000) 、MySQLは TEXT です。 また文字コードは UTF-8 なので、全角2000文字でもありません。 もしこの制限に引っ掛かる文字列型を扱う可能性がある場合は LongText を利用してください。 LongTextにした場合BLOBとして保存されるため、検索時に制限があります (LongText型の検索)。

Integer型のJavaクラス

Entityの検索や更新処理で、Integer型を操作する際は、Longクラスとして値を取得・設定します(Integerクラスではありません)。

Decimal型の丸めモード

Decimal型の場合、データの保存時に丸めた値で保存されます。 「丸めモード」には以下の種類があります(java.math.RoundMode)。

モード(java.math.RoundMode) 説明

UP

0から離れるようにする(正数切り上げ/負数切り上げ)

DOWN

0に近づける(正数切り下げ/負数切り下げ)

CEILING

正の無限大に近づける(正数切り上げ/負数切り下げ)

FLOOR

負の無限大に近づける(正数切り下げ/負数切り上げ)

HALF_UP

四捨五入

HALF_DOWN

五捨六入

HALF_EVEN

銀行型丸め

Select

Select型は選択ボックスの選択値ように、登録できる値を「値とラベル」のセットとして予め定義できるPropertyです。 値セットの定義方法は、複数のEntityで共有可能なSelectValueメタデータとして定義する方法(Global Value)と、 それぞれのPropertyごとに個別に定義する方法(Local Value)の2種類があります。

設定

次の項目を設定可能です。

設定項目 設定内容

Global Value

SelectValueメタデータを指定します。

Local Value

このPropertyに特化した選択可能項目の {値、ラベル} リストを指定します。 値はString型のため、数値、Boolean値として扱う場合は注意してください。

Global ValueLocal Value を共に設定した場合は、 Local Value が優先されます (Global Value がクリアされた状態で保存されます)。
Global Value を利用する場合は、 Local Value を全て削除して保存してください。
操作方法

Entityの検索や更新処理で、Select型Propertyを操作する際は、以下のクラスを利用します。

マッピングクラス
org.iplass.mtp.entity.SelectValue
(例)更新処理
EntityManager em = ManagerLocator.manager(EntityManager.class);

Entity entity = new GenericEntity("samples.Sample");
entity.setName("xxxxx");

//SelectValueの生成
SelectValue selectValue = new SelectValue("01");    //登録するためだけであれば、valueのみでOK

//SelectValueをPropertyにセット
entity.setValue("select", selectValue);

//登録
String oid = em.insert(entity);
(例)参照処理
EntityManager em = ManagerLocator.manager(EntityManager.class);

//検索(load)
String oid = "00001";
Long version  = 0;
Entity entity = em.load(oid, version, "samples.Sample");

//SelectValueの取得
//取得したEntityのPropertyにはSelectValueが設定されている
SelectValue selectValue = entity.getValue("select");

System.out.println(selectValue.getValue() + "=" + selectValue.getDisplayName());
Select型のソート順

Select型に対するソートは、定義での並び順が適用されます。

(例)ソート順の設定
value displayName

98

未開始

01

開始中

02

終了

00

エラー

99

キャンセル

上表の順番で定義した場合、value 値でソートせず、定義した順番「未開始 ~ キャンセル」でデータがソートされます。

AutoNumber

AutoNumber型はEntityデータの登録時に自動的に値を採番するPropertyです。 日付やユーザー情報などを利用した書式設定をすることが可能です。 データ登録時以外値を変更できません(読み取り専用)。

設定

次の項目を設定可能です。

設定項目 設定内容

開始値

採番を開始する番号を指定します。

既にデータが登録済みの状態でこの値を変更しても、カウンタはリセットされません。 カウンタの値をリセットしたい場合は、リセット機能を利用してください。

固定桁数

桁数を固定したい場合に指定します。 設定された桁数分、ゼロパディングした値が返されます。0を設定した場合はゼロパディングされません。

採番値が固定桁数を超えた場合は、そのまま採番値が利用されます。

採番ルール

採番する際のトランザクション制御を指定します。

ALLOW_SKIPPING 別トランザクションで採番

Entityの登録処理とは別トランザクションで採番するため、登録時の並列実効性は高まります。 ただし採番値のキャッシュや登録エラー時など、採番値の連続性を保証しません。

STRICT_SEQUENCE 同一トランザクションで採番

Entityの登録処理と同一トランザクションで採番するため、登録処理はシーケンシャルな処理になります。 採番値の連続性を保証する必要がある場合に指定します。

書式

登録する値をGroovyTemplate形式で書式指定することができます。

書式設定

書式で利用可能なバインド変数は以下のものです。

バインド変数 設定される値

nextVal()

次の採番された番号。最大桁数は18桁です。nextValの引数に採番単位とする UnitKey 値を指定することで、 そのKey値単位で番号を採番することも可能です。

yyyy

MM

dd

HH

時、24h表記

mm

ss

date

java.sql.Timestampのインスタンス

entity

登録対象のEntityデータ

user

登録者User情報。 ${user.xxxx} としてUserエンティティのプロパティを指定できます。

未指定の場合、採番された値が設定されます( ${nextVal() と同等)。

(例)書式設定
// `2018-01-01-0000001001` のようになります。
${yyyy}-${MM}-${dd}-${nextVal()}

// 年月単位で採番されます。
${nextVal(yyyy+MM)}

// select1というSelect型(SelectValue)プロパティの値単位で採番されます。
${nextVal(entity.select1.value)}
カウンタのリセット

Entityデータを他の環境からエクスポート/インポートで移行した場合は、内部で保持しているカウンタ値をリセットする必要があります。

AutoNumber型自体はUnique制約とはなっていないため、移行後の環境で重複した値が採番されてもエラーにはなりません。 AutoNumber型Propertyに対して、 OIDUnique Index を指定している場合は、重複が発生したタイミングでエラーになります。

AdminConsoleでのリセット

AdminConsole上は Current Value ボタンをクリックすることで、現在のカウンタ値の一覧を表示します。
リセットしたい UnitKey 行の Value を変更して保存してください。

UnitKey を利用していない場合、 UnitKey は空で表示されます。
UnitKey を利用している場合、他環境からデータを移行したタイミングでは一覧上にはデータが存在しません。 行を追加して値を設定してください。
既に登録されている UnitKey の行を削除することはできません。
ソースでのリセット

ソース上から直接現在値の取得やリセットを行いたい場合は、 EntityDefinitionManager を利用します。

//現在値の取得
EntityDefinitionManager#getAutoNumberCurrentValue(String definitionName, String propertyName);
EntityDefinitionManager#getAutoNumberCurrentValue(String definitionName, String propertyName, String subUnitKey);

//UnitKeyを利用している場合に、プロパティ内の全ての現在値を返します
EntityDefinitionManager#getAutoNumberCurrentValueList(String definitionName, String propertyName)

//リセット
EntityDefinitionManager#resetAutoNumberCounter(String definitionName, String propertyName, long startsWith);
EntityDefinitionManager#resetAutoNumberCounter(String definitionName, String propertyName, String subUnitKey, long startsWith);

Expression

Expression型は四則演算やCase文、スカラーサブクエリ(結果が1つになるクエリ)など、 Query機能の Value Expression として指定可能な式を設定することができるPropertyです。

設定

次の項目を設定可能です。

設定項目 設定内容

Result Type

式の結果として返す値のProperty型を指定します。未指定の場合はString型です。

指定可能な式は、Queryの Value Expression として有効な式になります。

(例)四則演算以外の例
case
  when integer1 = 50 then '△△△'
  when integer1 = 80 then '○○○'
  else '×××'
end
integer1 /  (select sum(integer1) from samples.Sample)
case
  when 50 = (select integer1 + integer2 from sample.Sample on .this=this)  then '△△△' (1)
  when 80 = (select integer1 + integer2 from sample.Sample on .this=this)  then '○○○'
  else '×××'
end
1 thisはoidとほぼ同じ意味です。逆に .oid=oid という表現は不可となっています。
四則演算で参照するプロパティの多重度が1以外の場合、正確な計算が実行されません。 多重度が1のプロパティに対してのみ利用してください。

Binary

Binary型は画像や文書ファイルなどのバイナリデータを扱うためのPropertyです。

設定

Binary型に特化した設定項目はありません。

操作方法

Entityの検索や更新処理で、Binary型Propertyを操作する際は、以下のクラスを利用します。

マッピングクラス
org.iplass.mtp.entity.BinaryReference
(例)更新処理

バイナリファイルをEntityに登録する場合は、BinaryReferenceを生成したうえでEntityにセットします。

EntityManager em = ManagerLocator.manager(EntityManager.class);

Entity entity = new GenericEntity("samples.Sample");
entity.setName("xxxxx");

//BinaryReferenceの生成
BinaryReference bin = null;
try (FileInputStream is = new FileInputStream(file)){

    //EntityManagerを利用してBinaryReferenceを生成
    bin = em.createBinaryReference(file.getName(), "image/gif", is);
} catch (FileNotFoundException e) {
    throw new ApplicationException("ファイルが取得できません。", e);
}

//生成したBinaryReferenceをEntityにセット
entity.setValue("binary", bin);

//登録
String oid = em.insert(entity);
(例)参照処理

Entityを検索したタイミングではBinaryReferenceとしてPropertyに値がセットされています。 BinaryReferenceにはバイナリ自体は格納されていません。 BinaryReferenceに紐づくバイナリを取得したい場合はEntityManagerを利用して取得します。

EntityManager em = ManagerLocator.manager(EntityManager.class);

//検索
String oid = "00001";
long version  = 0;
Entity entity = em.load(oid, version, "samples.Sample");

//BinaryReferenceの取得
//取得したEntityのPropertyにはBinaryReferenceが格納されている
BinaryReference bin = entity.getValue("binary");

//System.out.println(bin.getLobId()
//        + ", name=" + bin.getName() + ", type=" + bin.getType());

//バイナリの取得(Fileとして取得する場合)
//(一時的に)保存したいdirは別途指定すること
File file = new File(dir, bin.getName());

//EntityManagerを利用してバイナリのInputStreamを取得
try (FileOutputStream fos = new FileOutputStream(file);
    InputStream is = em.getInputStream(bin);
) {
    //この例では「org.apache.commons.io.IOUtils」を利用
    IOUtils.copy(is, fos);
} catch (IOException e) {
    throw new ApplicationException("ファイルが取得できません。", e);
}
(例)Web画面での参照処理

Webの画面上に表示させるような場合はimgタグを利用します。 imgタグで指定するActionを別途作成し、Resultのタイプとして Stream を指定します。 RequestContextに対してResultの StreamAttributeName に指定したAttributeにBinaryReferenceをセットすることで、 画像を表示することが可能になります。 (ResultのStreamタイプを利用することで、自身でStreamを取得する処理が不要になります)

この一連の実装は以下を参考にしてください。

  • Template例
    jsp/gem/generic/editor/binary/BinaryPropertyEditor_View.jsp

  • Action例
    gem/binary/download

    このActionクラスはJava Commandクラスに指定されたアノテーションから作成されたものです。 JavaCommandクラスは以下です。

    org.iplass.gem.command.binary.DownloadCommand

ユーティリティ機能

Binaryに対する最大ファイルサイズやMagicByteチェックの実行可否、ウィルススキャンの実行可否を mtp-service-config.xmlのWebFrontendServiceで定義できます。
設定内容の詳細は、WebFrontendServiceを参照してください。

またBinaryの永続化方法として、RDB(BLOBデータ)として保存するか、サーバ上にファイルとして保存するかを mtp-service-config.xmlのLobStoreServiceで定義できます。
設定内容の詳細は、LobStoreServiceを参照してください。

LongText

LongText型はString型ではサイズが足りない場合(String型の文字数制限)などの テキストデータを扱うためのPropertyです。 内部的にBinary型同様Lobまたはファイルとして管理しているため、検索時に制限があります。

設定

LongText型に特化した設定項目はありません。

LongTextについては、EQLを利用した検索条件の指定は完全にはできません。 LongTextに対する完全な検索機能を提供する場合は、 全文検索 機能を利用します。 このため汎用検索画面においても検索条件としてLongText型のPropertyは表示されません。

ただし、mtp-service-config.xmlにてPropertyServiceの設定を行うことで、先頭から一定文字数分の検索が可能になります。
設定内容の詳細は、PropertyServiceを参照してください。

Reference

Reference型はEntity間の参照関係を定義するためのPropertyです。 RDBではSQLのJoinを利用してTable間の結合を定義しますが、 iPLAssのEntityではプロパティとして参照関係を定義する事で同等の機能を実現します。

Referenceの構造

オブジェクトID (oid) で少し触れましたが、Reference型は参照しているEntityの oidversion を保持します。

entity property oid

この参照関係を利用することで、参照元のEntityを検索する際に参照先のEntity情報を取得できます。

EQLではFrom句でDBのJoinのように複数Entityを結合することができません。 RDBのJoinと同様の機能をEQLで実現する場合には、対象Entityに対するReferenceプロパティを作成します。 作成したReferenceプロパティをSelect句に指定したり、Where条件で絞り込むことができます。
(Expression型など、Select句に対してスカラーサブクエリとして他Entityを参照することは可能です)
「参照」(「順参照」)と「被参照」

Reference型には、指定した参照Entityに対する「順参照」と「被参照」という概念があります。

「順参照」は、当Entity(Referenceを定義しているEntity)が、参照Entityの、どのデータを利用するかを保持するための、当Entityの更新対象属性として扱う目的で定義します。 ですので当Entityデータを更新する際には、Entityに対してReference値を指定して更新する必要があります。

「被参照」は、当Entityが、参照Entityの、どのデータによって参照されているかを把握する目的で定義します、いわば逆引きです。 ですので当Entityを更新する際に、「被参照」として定義したPropertyに対して値を設定しても、参照関係が作成されるわけではありません。 「被参照」Propertyを定義することで、参照される側(この場合「被参照」Propertyを定義した当Entity)から参照Entityデータを取得することが可能になります。

「順参照」か「被参照」かは「被参照Property」を指定するかで決まります。

「被参照Property」が未指定の場合

「参照Entity」に対して「順参照」(「参照Entity」を参照する)

「被参照Property」を指定した場合

「参照Entity」に対して「被参照」(「参照Entity」から「被参照Property」名で参照される)

設定

次の項目を設定可能です。

設定項目 設定内容

参照Entity

参照関係にあるEntityを指定します。

参照関係

参照するEntityとの参照関係を指定します。
詳細は参照関係の指定を参照してください。

被参照Property、
操作履歴を被参照側のEntityに記録

このEntityが参照関係にあるEntityから参照される側(被参照)の場合に指定します。
詳細は被参照Propertyの指定を参照してください。

参照先のバージョン

参照先のデータとして取得するバージョンのポリシーを指定します。
詳細は参照先バージョンの指定を参照してください。

ソート条件

このPropertyの多重度が1以外の場合に、どの順番で取得するかを指定します。 参照先EntityのPropertyに対して、昇順/降順を指定します。

参照関係の指定

参照するEntityとの関係を指定します。 指定されたタイプによって、EntityデータCRUD時の動作が変わります。

ASSOCIATION 通常の参照

参照先Entityと特別な関係を持ちません。 このEntityデータが削除された場合、参照先のEntityデータは削除されません。

COMPOSITION 親子関係

参照先Entityを子として参照します。 このEntityデータが削除された場合、参照先のEntityデータも削除されます。

被参照Propertyの指定

iPLAssでは、参照する側がReference型のプロパティで参照先のEntityを指定することで、参照関係を構築します。 この状態だと、参照される側がどのEntityから参照されているかを把握することができません。 参照される側が参照しているEntityを把握したい場合に「被参照Property」を利用します。 「被参照Property」をSelect句などで利用することで、参照している側の情報を取得できます。

「被参照Property」に指定可能なPropertyは、「参照Entity」で指定したEntityのProperty定義に存在する 当Entityが参照先になっているReferencePropertyです。
操作ログを被参照側のEntityに記録

参照情報の実態は参照する側のEntityにあります。 このため参照先EntityのCRUD操作に関する操作ログは、参照する側のEntityに保存されます。 参照される側で参照先の操作ログを把握したい場合は、「操作ログを被参照側のEntityに記録」を true に設定します。

この設定が有効になるのは、「被参照Property」を指定した場合です。(未指定の場合、有効になりません)

この機能の主な利用用途としては 参照関係を定義する際の考慮があります。

参照先バージョンの指定

参照先のEntityがバージョン管理されている場合に、参照データとして取得するバージョンのポリシーを指定します。

参照先のEntityがバージョン管理していない場合は、バージョンは0で上書きされるため、 ここで指定した値は意味がありません。
CURRENT_BASE 最新バージョンを取得

参照先のEntityの最新バージョン(同一oid)のデータを取得します。

RECORD_BASE 保存時のバージョンを取得

データが保存された時の参照先のEntityのバージョン(同一oid)のデータを取得します。 保存後に参照先のEntityデータが更新されても、参照する情報は保存時の状態のまま変わりません。

AS_OF_EXPRESSION_BASE 特定のバージョンを取得

基準値に指定した条件を満たす参照先のEntityのバージョン(同一oid)のデータを取得します。

基準値の指定

「特定のバージョンを取得」を指定した場合、バージョンを特定するための基準値を指定します。 基準値は参照先Entityのバージョン管理方式により設定する値が異なります。

NUMBER BASE の場合

参照元Entityの数値Property名(versionなども指定可能)、または直接数値のリテラルを指定します。

TIME BASE の場合

参照元Entityの日時Property名(createDateなども指定可能)、または直接日時のリテラルを指定します。

操作方法

Entityの検索や更新処理で、Reference型Propertyを操作する際は、以下のクラスを利用します。

マッピングクラス
org.iplass.mtp.entity.Entity
(例)更新処理
EntityManager em = ManagerLocator.manager(EntityManager.class);

Entity entity = new GenericEntity("samples.Sample");
entity.setName("xxxxx");

//Reference用Entityの生成(登録済みであれば検索して取得してもOK)
//Entityの実装クラスGenericEntityを利用
Entity refEntity = new GenericEntity("samples.RefEntity");
refEntity.setOid("xxxxx");  //oidとversionをセットしておけばOK
refEntity.setVersion(0);
//生成したReference用EntityをEntityにセット
entity.setValue("reference", refEntity);

//MultipleのReference用Entityの生成(配列でセット)
List<Entity> multiReferences = new ArrayList<Entity>;
Entity refsEntity1 = new GenericEntity("samples.RefEntity");
refsEntity1.setOid("xxxxx");
refsEntity1.setVersion(0);
multiReferences.add(refsEntity1);
Entity refsEntity2 = new GenericEntity("samples.RefEntity");
refsEntity2.setOid("xxxxx");
refsEntity2.setVersion(0);
multiReferences.add(refsEntity2);

//参照が1件の場合でもEntityの配列でセット
entity.setValue("multiReference", multiReferences.toArray(new Entity[0]));

//登録
String oid = em.insert(entity);
(例)参照処理

多重度が1以外の場合の検索時は、loadとsearchEntityで挙動が異なります。
load時はEntityの配列で返ってきますが、searchEntity時はSearchResultの結果として、 紐付いているEntityの件数分別々のEntityレコードとして返ってきます。
(SearchResultで返ってくるListが、Referenceとして紐づいているEntityの件数分になる)

EntityManager em = ManagerLocator.manager(EntityManager.class);

//検索(load)
String oid = "00001";
long version  = 0;
Entity entity = em.load(oid, version, "samples.Sample");

//Reference Entityの取得
Entity refEntity = entity.getValue("reference");
Entity[] multiRefEntity = entity.getValue("multiReference");

//検索(searchEntity)
Query query = new Query()
    .select("multiReference.oid", "multiReference.name")
    .from("samples.Sample")
    .where(new Equals("oid", oid));

SearchResult<Entity> result = em.searchEntity(query);

System.out.println("result size = " + result.getList().size());

result.getList().forEach(entity2 -> {
    Entity multiRefEntity2 = entity2.getValue("multiReference");
});

このsearchEntityの仕様により、汎用検索画面ではデフォルトとして多重度が1以外のReference Propertyは出力対象としていません。 汎用検索画面の設定で多重度が1以外のReference項目を検索結果として表示するように定義した場合は、同一のoidで複数のレコードが表示されます。

参照関係を定義する際の考慮

Entityに対して「順参照」用のReferenceプロパティを定義すると、当Entityデータの更新時に、 参照しているEntityデータ件数分の属性(oid、versionのセット)を更新しなおします。 参照先Entityの件数が少ない場合は特にレスポンス的な問題は発生しませんが、参照先Entityが大量の場合はレスポンスにも影響があります。

例えば、親子関係があるEntityで子側のEntityが大量の件数となるような場合は、子から親に「順参照」の定義をすることも1つの方法です。

entity reference mappedby

この場合、親Entityの属性は親Entityの属性のみ更新するような画面を作成して対応する必要があります。 子Entityからみると親Entityに対する参照関係は1なので、更新時のレスポンスも問題ありません。

親Entityで排他制御する場合

上のように、子Entityから親Entityに対して「順参照」を定義した場合、子Entityを更新しても親Entityは更新されません。 複数の子Entityを同時に更新する可能性がある場合に、親Entity側で排他制御を行いたい時はこのままだと制御できません。

これを回避するには子Entityの更新時に親Entityを強制的に更新させます。 更新処理は子EntityのEventListenerか独自に作成したCommandで行います。 EventListenerでの実装がActionやCommandなどをカスタマイズする必要がないので容易ですが、 1処理の中で複数の子Entityを一括で親Entityに紐づけるような場合は、EventListenerではなくCommandで実装してください。
(EventListenerで実装した場合、子Entityの件数分、親Entityを更新する処理が実行されることになります)

(例)EntityEventListenerで参照Entityを強制的に更新する(Script形式)

EventListenerの beforeInsert beforeUpdate beforeDelete で以下のScriptを実行します。

import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.entity.Entity;
import org.iplass.mtp.entity.UpdateOption;

EntityManager em = ManagerLocator.manager(EntityManager.class);

//parent取得(親Entityをparentプロパティとして参照している場合)
Entity parent = entity.getValue("parent");  //対象EntityはentityとしてListenerにバインドされている

//System.out.println("parent oid=" + parent.getOid() + ",version=" + parent.getVersion());

//更新Optionを生成
UpdateOption option = new UpdateOption();
//更新Propertyを設定(例:更新日)。なにかを指定しないとNullPointerが発生する
option.setUpdateProperties(Entity.UPDATE_DATE);

//強制更新設定(変更がなくても更新)
option.setForceUpdate(true);

//parentの更新
em.update(parent, option);
被参照時の操作ログについて

子から親に「順参照」を定義する場合、ユーザーがデータを操作するための詳細画面としては 子Entityの詳細画面をメインで利用するという使い方が多いと思います。 このとき詳細画面上に操作ログを表示した場合、親Entityの操作ログは子Entityの操作ログ上には表示されません。

そこで、親Entityの操作ログを子Entityの操作ログにも出力する機能が「操作履歴を被参照側のEntityに記録」チェックです。 親EntityのPropertyとして、子Entityに対する「被参照」を定義して、「操作履歴を被参照側のEntityに記録」をチェックすることで、親Entityの操作ログが子Entityの操作ログに記録されるようになり、子Entityの詳細画面から親Entityの操作ログが参照可能になります。

3.2. Validator

提供Validator

標準で提供しているPropertyのValidatorです。

Type 説明 Java型

NotNull

入力の有無を検証します。Propertyで設定する Required と連動します。

*

Length

文字列の長さを検証します。

String

Range

数値の範囲を検証します。

Number

Regex

正規表現を利用して値を検証します。

String、Number

BinarySize

バイナリのサイズを検証します。

BinaryReference

BinaryType

バイナリのタイプを検証します。

BinaryReference

Exists

Referenceの参照データの存在を検証します。

Entity

Scripting

GroovyScript書式で検証ロジックを実装します。

*

Java Class

Java Classで検証ロジックを実装します。

*

対応するJava型以外のProperty型に対してValidatorを指定した場合、 検証時に EntityRuntimeException が発生します。

Not Null Scripting Java Class 以外は、値が null の場合はチェックされません(true)。

NotNull

入力の有無を検証します。 AdminConsole上の編集画面では、Required の設定と連動して追加、削除されます。

以下の場合にエラーとなります。

  • 値が null

  • String型の場合、値が空

  • 配列の場合、サイズが0

対応するJava型

すべての型で利用可能です。

設定

NotNullに特化した設定項目はありません。

Length

文字列の長さを検証します。

以下の場合にエラーとなります。

  • checkBytesfalse の場合、値の長さが min 未満

  • checkBytesfalse の場合、値の長さが max より上

  • checkBytestrue の場合、値のバイト数が min 未満

  • checkBytestrue の場合、値のバイト数が max より上

対応するJava型

String型で利用可能です。

設定
設定項目 設定内容

min

最小値を指定します。

max

最大値を指定します。

checkBytes

バイト数でチェックする場合、trueにします。

Range

数値の範囲を検証します。

以下の場合にエラーとなります。

  • grater than min valuetrue の場合、値が min 以下

  • grater than min valuefalse の場合、値が min 未満

  • less than max valuetrue の場合、値が max 以上

  • less than max valuefalse の場合、値が max より上

対応するJava型

Number型で利用可能です。 Number型に対応するPropertyタイプは Integer Float Decimal です。

設定
設定項目 設定内容

min

最小値を指定します。

grater than min value

最小値を含まない場合、trueにします。

max

最大値を指定します。

less than max value

最大値を含まない場合、trueにします。

Regex

正規表現を利用して値を検証します。

以下の場合にエラーとなります。

  • 値が正規表現にマッチしない場合

(例)半角英数字
[0-9a-zA-Z]+
(例)ひらがな
[\\u3040-\\u309F]+
対応するJava型

String型、Number型で利用可能です。 Number型の場合、 toString() した値に対して検証します。 Number型に対応するPropertyタイプは Integer Float Decimal です。

設定
設定項目 設定内容

pattern

正規表現式を指定します。

BinarySize

バイナリのサイズを検証します。

以下の場合にエラーとなります。

  • バイナリのサイズが min 未満

  • バイナリのサイズが max より上

対応するJava型

BinaryReference型で利用可能です。

設定
設定項目 設定内容

min

最小値(byte)を指定します。

max

最大値(byte)を指定します。

BinaryType

バイナリのタイプを検証します。

以下の場合にエラーとなります。

  • バイナリのタイプが正規表現にマッチしない場合

対応するJava型

BinaryReference型で利用可能です。

設定
設定項目 設定内容

acceptMimeTypesPattern

mimeタイプを指定します(正規表現)。

Exists

Referenceの参照データの存在を検証します。被参照は対象外です。

以下の場合にエラーとなります。

  • 指定された oid version に一致するEntityデータが存在しない

対応するJava型

Entity型で利用可能です。 Entity型に対応するPropertyタイプは Reference のみです。

設定

Existsに特化した設定項目はありません。

Packageや独自で作成した複数Entityの一括登録処理の場合は、Entityの登録順番に注意が必要です。 PackageはEntityの順番指定ができないので、分割するかValidationを実行しないことも検討してください。

Scripting

GroovyScript書式で検証ロジックを実装します。

以下の場合にエラーとなります。

  • scriptの戻り値が false

対応するJava型

すべての型で利用可能です。

設定
設定項目 設定内容

script

GroovyScriptを指定します。 戻り値としてBoolean(true:OK、false:NG)を返すように実装する必要があります。

bind variable as array type

多重度が1ではない場合に、value変数に配列をバインドするか、 配列分ループしてvalueにバインドするかを指定します。
true の場合、配列をバインドします。

利用可能な変数

利用可能なバインド変数は以下のものです。

バインド変数 設定される値

entity

対象のEntityデータ。

propertyName

プロパティ名

value

プロパティ値。各Propertyに対応するJava型が格納されています。

context

ValidationContext。 ValidationContextにsetAttributeされた値は、${key} 形式でエラーメッセージに埋め込みが可能となります。

(例)ReferencePropertyに対する存在チェック
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.Entity;

//値が未設定の場合はOK
if (value == null) {
    return true;
}

EntityManager em = ManagerLocator.manager(EntityManager.class);

//対象のReferenceProperty
Entity refValue = (Entity)value;    //valueにProperty値が入っている(バインド)

//存在チェック
Entity refData = em.load(refValue.getOid(), refValue.getVersion(), refValue.getDefinitionName());

if (refData == null) {
    return false;   //存在しないのでNG
} else {
    return true;    //存在するのでOK
}

Java Class

以下のインターフェースを実装したJavaクラスにより検証します。

org.iplass.mtp.entity.PropertyValidator

以下の場合にエラーとなります。

  • validateの戻り値が false

対応するJava型

すべての型で利用可能です。

設定
設定項目 設定内容

Java Class Name

PropertyValidatorを実装したクラス名を指定します。

bind variable as array type

多重度が1ではない場合に、value変数に配列をバインドするか、 配列分ループしてvalueにバインドするかを指定します。
true の場合、配列をバインドします。

PropertyValidatorの例
import org.iplass.mtp.entity.PropertyValidator;
import org.iplass.mtp.entity.ValidationContext;

public class CustomPropertyValidator implements PropertyValidator {

    @Override
    public boolean validate(Object value, ValidationContext context) {
        if (value == null) {
            return true;
        }

        // Stringは不可
        if (value instanceof String) {
            // contextにセットした値はエラーメッセージに埋め込み可能です。
            // 例えばメッセージとして「${type}型は許可されません。」と定義すると、
            // 「String型は許可されません。」に変換されます。
            context.setAttribute("type", "String");
            return false;
        }
        return true;
    }

}

メッセージの設定

Validateエラー時のメッセージを指定します。

メッセージの指定は、直接文字列を指定する方法とメタデータのMessageを利用する方法の2種類あります。

設定
設定項目 設定内容

Message(Direct)

メッセージを直接指定します。

Message Category
Message Id

メタデータのMessageを選択します。メタデータのMessageを利用することで、メッセージを共有・管理することができます。
メッセージの詳細はメッセージの多言語設定を参照してください。

Code

メッセージコードを指定します。この項目は任意です。 バッチ処理やWebサービスなどの独自処理内でコードをレスポンスとして返したい場合などに利用します。

Message(Direct)Message Id が両方指定されている場合は、 Message(Direct) が優先されます。
mtp/validation カテゴリに定義されてる標準的なメッセージを利用することも可能です。
利用可能な変数

メッセージ文言として、プロパティ名や値をバインド書式(${xxx})で参照することができます (DirectでもメタデータのMessageでも参照できます)。

利用可能なバインド変数は以下のものです。

バインド変数 設定される値

name

プロパティ名

entityName

エンティティ名

min

Length、Range、BinarySizeの min に設定した値

max

Length、Range、BinarySizeの max に設定した値

reference

Existsの存在しないデータ値。複数ある場合はカンマ区切り

min、max、referenceについては、他のタイプの場合はバインドされていないため ${min}${max}${reference} とそのまま出力されます。

上記の他、ValidationContextに setAttribute された値は、${key} 形式でエラーメッセージに埋め込みが可能となります。 具体的な例は、 Java Class を参照してください。

Validationの操作方法

汎用画面を利用してEntityの更新処理を行う場合は、汎用画面側でValidatorエラーのハンドリングは自動的に行われます。 ここではバッチやWebサービスを利用した独自のEntity更新処理を実装する場合のValidatorエラーハンドリングの方法を説明します。

Entity更新時の操作方法

EntityManagerを利用した insertupdate 時には 自動的にValidatorチェックが実行されます。 エラーが発生した場合は EntityValidationException がthrowされます。 この EntityValidationException 内に、エラーとなった ValidateError が格納されています。

import org.iplass.mtp.entity.EntityValidationException;
import org.iplass.mtp.entity.ValidateError;

EntityManager em = ManagerLocator.manager(EntityManager.class);

try {
    //登録の場合
    em.insert(entity);

    //更新の場合
    UpdateOption option = new UpdateOption();
    option.setUpdateProperties();
    em.update(entity, option);
} catch (EntityValidationException e) { //EntityValidationExceptionがthrow
    //ValidateErrorの取得
    ValidateError[] errors = e.getValidateResult();

    Arrays.stream(errors).forEach(error -> {
        //対象Property名
        System.out.println("propertyName =" + error.getPropertyName());

        //Listなのは同一Propertyに対する複数Validator用
        //エラーコードとエラーメッセージは同じサイズ
        //エラーコードが未指定の場合は""
        List<String> errorCodes = error.getErrorCodes();
        List<String> errorMessages = error.getErrorMessages();

        for (int i = 0; i < errorMessages.size(); i++) {
            System.out.println(
                error.getPropertyName()
                + " error = [" + errorCodes.get(i) + "]"
                + errorMessages.get(i));
        }
    });
}

Entityのデータ移行時など、データ更新時にValidatorチェックを行いたくない場合は、 InsertOptionUpdateOption を利用します。

手動でのValidatorチェック

EntityManager#validate を利用することで手動でValidatorチェックを実行できます。 この場合、チェック結果は「ValidateResult」として返ってきます。

import org.iplass.mtp.entity.ValidateResult;

EntityManager em = ManagerLocator.manager(EntityManager.class);

ValidateResult result = em.validate(entity);    //Validatorチェックの実行

if (result.hasError()) {
    //ValidateErrorの取得
    ValidateError[] errors = result.getError();
    
}

3.3. Normalizer

プロパティの値を正規化するための定義です。 正規化は検証の直前に実行されます。

正規化は、同一のプロパティの値に対して複数回呼び出される可能性があります。 htmlサニタイジング処理のような、複数回呼び出された場合に問題がある処理はPropertyNormalizerで実装しないでください。

提供Normalizer

標準で提供しているPropertyのNormalizerです。

Type 説明 Java型

Trim White Space

文字列の前後の空白を除去します。

String

Newline Normalizer

改行コードを統一します。

String

ICU Transliterator

ICU4JのTransliteratorを利用して変換を行います。

String

Regex Replace

正規表現を利用して値を置換します。

String

Unicode Normalizer

Unicode正規化を実施します。

String

Scripting

GroovyScript書式で正規化ロジックを実装します。

*

Java Class

Java Classで正規化ロジックを実装します。

*

Trim White Space

文字列の前後の空白を除去します。 AdminConsole上の編集画面では、Trim White Space の設定と連動して追加、削除されます。

対応するJava型

String型で利用可能です。

設定

Trim White Spaceに特化した設定項目はありません。

Newline Normalizer

改行コードを統一します。 AdminConsole上の編集画面では、Unify Line Breaks Code の設定と連動して追加、削除されます。

対応するJava型

String型で利用可能です。

設定
設定項目 設定内容

Line Breaks Code

改行コードを指定します

ICU Transliterator

ICU4JのTransliteratorを利用して変換を行います。

対応するJava型

String型で利用可能です。

設定
設定項目 設定内容

Transliterator Id

ICU4JのTransliteratorのIDを指定します。

Regex Replace

正規表現を利用して値を置換します。

対応するJava型

String型で利用可能です。

設定
設定項目 設定内容

Regex

置換対象の正規表現式を指定します。

Replacement

置換後文字列を指定します。

Unicode Normalizer

Unicode正規化を実施します。

対応するJava型

String型で利用可能です。

設定
設定項目 設定内容

Form

Unicode正規化形式を指定します。

Scripting

GroovyScript書式で正規化ロジックを実装します。

対応するJava型

すべての型で利用可能です。

設定
設定項目 設定内容

script

GroovyScriptを指定します。 戻り値として正規化後の値を返すように実装する必要があります。

bind variable as array type

多重度が1ではない場合に、value変数に配列をバインドするか、 配列分ループしてvalueにバインドするかを指定します。
true の場合、配列をバインドします。

利用可能な変数

利用可能なバインド変数は以下のものです。

バインド変数 設定される値

entity

対象のEntityデータ。

propertyName

プロパティ名

value

プロパティ値。各Propertyに対応するJava型が格納されています。

context

ValidationContext。

(例)接頭辞を付与する
if (value == null) {
    return null;
}
if (!value.startsWith('p_') {
    return 'p_' + value;
} else {
    return value;
}

Java Class

以下のインターフェースを実装したJavaクラスにより正規化します。

org.iplass.mtp.entity.PropertyNormalizer

対応するJava型

すべての型で利用可能です。

設定
設定項目 設定内容

Java Class Name

PropertyNormalizerを実装したクラス名を指定します。

bind variable as array type

多重度が1ではない場合に、value変数に配列をバインドするか、 配列分ループしてvalueにバインドするかを指定します。
true の場合、配列をバインドします。

PropertyNormalizerの例
import org.iplass.mtp.entity.PropertyNormalizer;
import org.iplass.mtp.entity.ValidationContext;

public class CustomPropertyNormalizer<String> implements PropertyNormalizer {
    public String normalize(Object value, ValidationContext context) {
        if (value == null) {
            return null;
        }

        return value.toString().replace(".", "_");
    }
}

3.4. 高度な設定

インデックス設定

検索処理の高速化のためのRDBのIndexのような機能として、Propertyに対するIndexを設定できます。 Indexを設定すると検索時は高速化されますが、データ更新時のパフォーマンスに影響が発生するため、設定時は考慮が必要です。

Index設定には以下の種類があります。

タイプ 説明

NON_INDEXED

Indexを利用しません。

UNIQUE

一意のIndexを作成します。重複データを登録しようとした場合、エラーになります。

UNIQUE_WITHOUT_NULL

一意のIndexを作成します。ただし null の場合は重複を許可します。

NON_UNIQUE

一意ではないIndexを作成します。

Indexの制限事項

Indexに関する注意点、制約事項を説明します。

  • Property単位でのみ設定が可能です。
    複合Index(複数Propertyの結合)はサポートしていません。

  • UNIQUEUNIQUE_WITHOUT_NULL はEntity単位での値の重複をチェックします。
    Entity更新時に重複がある場合はエラーとなります。

  • 多重度が1以外のPropertyはIndexを指定できません。

  • Expression Binary LongText Refernce はIndexを指定できません。

  • Entityのバージョン管理を行う場合、 UNIQUEUNIQUE_WITHOUT_NULL として指定したPropertyは変更不可になります。 Entity定義の保存時に自動的に CanEdit = false として登録されます。

  • 既に登録済みのEntityデータが存在する場合にIndex Typeを変更すると、Entity定義の保存時にIndexの再作成処理が実行されます。 大量データが登録されている場合などは考慮が必要です。
    UNIQUEUNIQUE_WITHOUT_NULL の場合、一意でないデータが存在すると再作成時にエラーが発生し、定義自体が保存できません。

Unique Indexに対するMySQL上での制約について

UNIQUEUNIQUE_WITHOUT_NULL は、バックエンドでRDBのUnique Indexを利用しています。 MySQLではUnique Indexのbyte制限として767byteまでしか格納することができません。 このため、 UNIQUEUNIQUE_WITHOUT_NULL を指定した場合は、 DBの文字コードによって格納できる最大の値長に制約が発生します (データ登録時にエラーになります)。

データ暗号化

当該カラムのデータを暗号化してDBに格納したい場合に設定します。 DB/OSなどが持つ透過的暗号化機能を利用することを推奨しますが、ライセンス費用の問題やインフラ環境で暗号化サポートしてない場合など、それらの利用が難しい場合、当該機能を利用してください。 なお、当該機能を利用する場合、アプリケーションの機能的な制限が入ります。

暗号化のモードとして以下の2つ用意をしています。

モード インデックス化 暗号化強度 検索条件指定 備考

ECBモード

可能

弱い

完全一致のみサポート

集計はカウントのみ可能

CBCモード

不可

強い

不可

集計はカウントのみ可能

暗号化した場合の制限事項

暗号化に関する注意点、制約事項を説明します。

  • 検索は ECBモード の場合かつ完全一致検索のみ可能。関数の適用、ソートは不可。

  • 未暗号化、暗号化を切り替えた場合、プロパティの実データは引き継がれない。

  • ECBモードCBCモード を切り替えた場合、プロパティの実データは引き継がれない。

  • 暗号化しているプロパティの型を変更した場合、以下のパターン以外は実データは引き継がれない。
    Select型、 AutoNumber型、 Boolean型、 Integer型、 Float型、 Decimal型、 Date型、 DateTime型、 Time型 → String型
    Boolean型 → Select型
    暗号化していない場合と比較し、数値型間の相互変換、日付型間の相互変換、String型からLongText型への変換がされない。

  • Decimal型のscaleを変更した場合、自動的にデータの洗い替えは行われない。

mtp-service-config.xmlの設定変更

プロパティ単位の暗号化を利用する場合、PropertyEncryptionServiceにて、暗号化アルゴリズムなどの設定を行ってください。

暗号化アルゴリズムは複数定義することができます。 新規に保存される値は一番後に定義された暗号化アルゴリズムを利用して暗号化されます。

4. SelectValue

SelectValueは、Entityの Select 型Propertyの選択値を定義するためのものです。

SelectValueメタデータとして定義することで、複数のEntity間や複数のProperty間で選択可能な値のセットを使いまわすことができます。

4.1. SelectValueの作成

SelectValueアイコンを右クリックして「SelectValueを作成する」を選択してください。

4.2. 設定

設定項目 設定内容

value

値を指定します。String型のため、数値、Boolean値として扱う場合は注意してください。

display name

表示名(ラベル)を指定します。

5. StorageSpace

5.1. StorageSpaceについて

iPLAssでは、AdminConsoleなどを利用して、動的にEntityの定義を変更することが可能です。
これら動的に定義されたEntityのデータは、StoreServiceに定義されたStorageSpaceに格納されます。

標準のStorage Space設定

iPLAssの初期設定では3つのStorageSpaceが定義されています。

<!-- Entity Store Settings -->
<service>
  <interface>org.iplass.mtp.impl.datastore.StoreService</interface>

  <property name="dataStore" class="org.iplass.mtp.impl.datastore.grdb.GRdbDataStore">
    <property name="storageSpace">
      <property name="storageSpaceName" value="default" />
      ・・・・・
    </property>
    <property name="storageSpace">
      <property name="storageSpaceName" value="mtp" />
      <property name="tableNamePostfix" value="MTP" />
      ・・・・・
    </property>
    <property name="storageSpace">
      <property name="storageSpaceName" value="user" />
      <property name="tableNamePostfix" value="USER" />
      ・・・・・
    </property>
  </property>
</service>

どのStorageSpaceにデータを保存するかはEntity単位で指定します。 iPLAssの標準Entityであるmtp配下のEntityは以下のStorageSpaceに保存されるようになっています。

Entity Storage Space

mtp.auth.User

user

それ以外のEntity(mtp.*.)

mtp

標準で定義されているStorageSpace usermtp については、基盤としての利用を前提にしているため、 アプリで作成するEntityでは利用しないでください。

アプリで作成するEntityについては、通常StorageSpaceが未指定のため default というStorageSpaceに保存されます。

entity storagespace storage

StorageSpaceの機能として、アプリで独自のStorageSpaceを追加することも可能になっています(service-config単位、Tenant単位ではありません)。

独自のStorageSpaceを定義することで

  • 一部大量データが格納されるEntityと、その他のEntityをそれぞれ別のStorageSpace(物理テーブル)に格納することができる

  • 各StorageSpace単位で物理テーブルの特性を変更することが可能なので、Entityの特性毎にうまく使い分ければ、 RDB上のテーブルスペースが効率的に利用され、RDBのファイルサイズを小さくすることができる

  • StorageSpace毎にパーティション定義内容を変更することができる

  • EntityのPropertyに対して Store Col Name を指定することで、 プロパティデータの物理格納カラムを独自で定義したテーブルカラムに直接格納することができる。
    これを利用して複合Indexの定義などのRDBネイティブの機能を利用することができる

などのカスタマイズが可能になります。

StorageSpace の決定タイミング

Entity の StorageSpace が決定するタイミングは、次の3パターンです。

  1. Entity 作成時

    1. Entity 作成時に、StorageSpace default が設定されます。

  2. Entity の StorageSpace 変更時

    1. StorageSpace 設定の変更のみ行われます。

    2. 運用で利用中でデータが存在する Entity の StorageSpace を変更する場合は、データの移行が必要となります。StorageSpace変更時の注意点を参照ください。

  3. バッチツール - Storage Space Migration によるデータ移行時

    1. ツール実行時に、StorageSpace 設定の変更および、データ移行を行います。

次は、このStorageSpace定義を実際に構成するテーブル構造について説明します。

テーブル構造

StorageSpaceはそれぞれで以下のテーブルセットで構成されます。

テーブル名 用途

obj_store

Entityのデータを格納する汎用テーブル。動的なEntity定義に対応するため予め複数のカラムが定義されている。
rbは削除データの格納用。

obj_store_rb

obj_ref

Entityデータ間の参照情報を格納するテーブル。
rbは削除データの格納用。

obj_ref_rb

obj_unique_str

UniqueIndexが設定されたプロパティ値を格納するテーブル群。
プロパティ型に合わせて、それぞれ定義されている。

obj_unique_ts

obj_unique_num

obj_unique_dbl

obj_unique_date

obj_index_str

Indexが設定されたプロパティ値を格納するテーブル群。
プロパティ型に合わせて、それぞれ定義されている。

obj_index_ts

obj_index_num

obj_index_dbl

obj_index_date

このテーブルセットがStorageSpaceごとに必要になります。

この中でも重要となるのが obj_store テーブルです。

「obj_store」は

  • Entityとして定義されるすべてのデータが格納される

  • 汎用的に利用するため、あらかじめ文字列型、数値型、日付型、浮動小数点型それぞれ、複数のカラムが定義されている

  • Index、UniqueIndex付のカラムもあらかじめ定義されている

  • Entityのプロパティはいずれかのカラムに自動的にマッピングされる
    (テナント、Entity単位で、それぞれどのカラムにどのプロパティ値が格納されるかは異なる)

  • 事前にテーブルに定義されているカラム数以上のプロパティがEntityに定義された場合、PageNoを用いて1データを複数行に格納する。

という役割を持っています。

実際にデータが格納されるイメージを示します。

データの格納イメージ
制御用共通カラム プロパティ値格納用汎用カラム Index値格納カラム

(TenantID)

(Entity定義ID)

(oid)

(name)

文字列Property

数値Property

IndexProperty

tenant_id

obj_def_id

obj_id

pg_no

obj_name

STR_1

STR_2

NUM_1

NUM_2

ISTR_1

ISTR_2

・・・

1

Product

00001

0

productA

string101

string202

110

istring101

istring102

1

Product

00002

0

productB

string201

string202

210

istring201

istring202

1

Product

00003

0

productC

string301

string302

310

istring301

istring302

1

QA

00001

0

qa001

aaa

bbb

1

QA

00001

1

ccc

ddd

1

QA

00002

0

qa002

eee

fff

1

QA

00002

1

ggg

1

Point

00001

0

point1

OK

100

1

Point

00002

0

point2

NG

200

Entityに定義されるPropertyの型ごとの数に対して、事前にテーブルに定義された各型ごとのカラムが足りなくなった場合は、 pg_noを利用して、複数レコードで保持します。
Query(EQL)を利用して検索されるときは、基盤内部で自動的に自己結合することで疑似的に1レコードとして返しています。

このようにiPLAss基盤内の仕様に沿った汎用的なテーブルを利用して、動的に定義されたEntityのプロパティデータを格納し、 EntityManagerを通してデータを制御しています。

次は、 obj_store テーブルに対する仕様について説明します。

obj_storeの仕様

EntityManagerでEntityデータを制御するために、obj_store テーブルの構造は一定の仕様(制約)があります。

テーブルは「システム共通項目(変更不可)」、「UniqueIndex値格納カラム」、「Index値格納カラム」、「Property値格納汎用カラム」に分かれます。 このうち「システム共通項目(変更不可)」以外は、service-configの storageSpace 定義と関連します。

標準で定義されている default StorageSpaceをもとに説明します。

ここではMySQLの標準設定を例に説明します。RDBによって標準で定義されている値は異なります。
<!-- Entity Store Settings -->
<service>
  <interface>org.iplass.mtp.spi.datastore.StoreService</interface>

  <property name="dataStore" class="org.iplass.mtp.impl.datastore.grdb.GRdbDataStore">
    ・・・・
    <property name="storageSpace">
      <property name="storageSpaceName" value="default" />
      <property name="varcharColumns" value="64" />
      <property name="decimalColumns" value="32" />
      <property name="timestampColumns" value="32" />
      <property name="doubleColumns" value="16" />
      <property name="useExternalIndexedTable" value="true" />
      <property name="indexedVarcharColumns" value="5" />
      <property name="indexedDecimalColumns" value="4" />
      <property name="indexedTimestampColumns" value="4" />
      <property name="indexedDoubleColumns" value="4" />
      <property name="useExternalUniqueIndexedTable" value="true" />
      <property name="uniqueIndexedVarcharColumns" value="2" />
      <property name="uniqueIndexedDecimalColumns" value="2" />
      <property name="uniqueIndexedTimestampColumns" value="2" />
      <property name="uniqueIndexedDoubleColumns" value="2" />
    </property>
    ・・・・
  </property>
</service>

各Propertyについて説明します。

設定項目 設定内容

storageSpaceName

Entity定義で選択する際に表示されるStorage Space名を指定します。
標準で、 defaultmtpuser が定義されているので、それ以外の名前を指定してください。

tableNamePostfix

StorageSpace用のテーブルに付加する接尾語を指定します。英数字のみ利用してください。
標準で、 defaultmtpuser が定義されているので、それ以外の名前を指定してください。

「テーブル構造」で説明したテーブルセットの各テーブル名に、ここで指定したPostfixを追加したテーブルが必要になります。

obj_storeの場合、

"obj_store" + __ + Postfix

となります。アンダースコア―を2つでつなげます。
例えば、 mtp StorageSpaceの場合は、obj_store__mtp となります。 obj_indexobj_unique_index なども同様です。

varcharColumns

文字列型のプロパティを格納するための列数を指定します。
ここで指定した数分、「STR_1」、「STR_2」、「STR_n」の列が必要になります。

decimalColumns

Decimal型のプロパティを格納するための列数を指定します。
ここで指定した数分、「NUM_1」、「NUM_2」、「NUM_n」の列が必要になります。

timestampColumns

Timestamp型のプロパティを格納するための列数を指定します。
ここで指定した数分、「TS_1」、「TS_2」、「TS_n」の列が必要になります。

doubleColumns

浮動小数点型のプロパティを格納するための列数を指定します。
ここで指定した数分、「DBL_1」、「DBL_2」、「DBL_n」の列が必要になります。

useExternalIndexedTable

この設定はobj_storeのルールとは直接関係はありません。

StorageSpaceにおける外部INDEXテーブル(obj_index 系テーブル)を利用するかを指定します。デフォルトは true です。

indexedVarcharColumns

Index指定された文字列型のプロパティを格納するための列数を指定します。
ここで指定した数分、「ISTR_1」、「ISTR_2」、「ISTR_n」の列が必要になります。

indexedDecimalColumns

Index指定されたDecimal型のプロパティを格納するための列数を指定します。
ここで指定した数分、「INUM_1」、「INUM_2」、「INUM_n」の列が必要になります。

indexedTimestampColumns

Index指定されたTimestamp型のプロパティを格納するための列数を指定します。
ここで指定した数分、「ITS_1」、「ITS_2」、「ITS_n」の列が必要になります。

indexedDoubleColumns

Index指定された浮動小数点型のプロパティを格納するための列数を指定します。
ここで指定した数分、「IDBL_1」、「IDBL_2」、「IDBL_n」の列が必要になります。

useExternalUniqueIndexedTable

この設定はobj_storeのルールとは直接関係はありません。

StorageSpaceにおける外部INDEXテーブル(obj_unique_index 系テーブル)を利用するかを指定します。デフォルトは true です。

uniqueIndexedVarcharColumns

Unique Index指定された文字列型のプロパティを格納するための列数を指定します。
ここで指定した数分、「USTR_1」、「USTR_2」、「USTR_n」の列が必要になります。

uniqueIndexedDecimalColumns

Unique Index指定されたDecimal型のプロパティを格納するための列数を指定します。
ここで指定した数分、「UNUM_1」、「UNUM_2」、「UNUM_n」の列が必要になります。

uniqueIndexedTimestampColumns

Unique Index指定されたTimestamp型のプロパティを格納するための列数を指定します。
ここで指定した数分、「UTS_1」、「UTS_2」、「UTS_n」の列が必要になります。

uniqueIndexedDoubleColumns

Decimal型のプロパティを格納するための列数を指定します。
ここで指定した数分、「UDBL_1」、「UDBL_2」、「UDBL_n」の列が必要になります。

customPartition

この設定はobj_storeのルールとは直接関係はありません。

ただしMySQLの場合、自動でPartitionが拡張できないので、テナント作成用ToolであるTenantManagerで テナントを作成・削除する際にPartitionの作成・削除を行っています。 その際、この設定が true のStorageSpaceについてはPartitionに対する処理を行いません。

Partitionを利用する場合に、標準のPartitionと異なるPartitionを利用するかを指定します。 デフォルトが false のため、標準のPartitionの場合は指定する必要はありません。

標準のPartitionとは

obj_store${tableNamePostfix}_テナントID

の命名規則に則って、テナント単位でPartitionを作成しているものです。

Entityのプロパティ型と列の型の対応について

EntityのPropertyで指定された型によって、以下のカラムに値が格納されます。

カラムの型 対象となるEntityプロパティの型

Varchar

AutoNumber、Boolean、Select、String、LongText、Binary

Timestamp

Date、Datetime、Time

Decimal

Decimal、Integer

Double

Float

このようにservice-configに定義されたStorageSpace定義に沿った obj_store を作成することで、 EntityManagerがEntityデータを自動的に制御します。

5.2. カスタマイズ

「obj_storeの仕様」に則って obj_store テーブルを作成することで、独自のStorageSpaceを利用することができます。

これによって、例えば、

  • 大量データが格納されるEntityのために order StorageSpaceを準備し、 OrderEntityは order StorageSpaceに格納する

  • プロパティ数が少ないEntity用に small StorageSpaceとして、文字列型、数値型、日付型のカラムを3個ずつだけ定義する

  • 数値型のPropertyが多いEntity用に num StorageSpaceとして、数値型のカラムを300個定義して、日付型は1個だけにする

など、Entityの特性毎にうまく使い分ければ、RDB上のテーブルスペースが効率的に利用され、RDBのファイルサイズを小さくすることができます。 また、汎用カラム数がオーバーした場合に利用される pg_no による疑似レコード化も抑えることができます。

entity storagespace custom

独自のStorageSpaceを作成するには、service-configのStorageSpace定義に対応するStorageSpace用のテーブルセットを作成する必要があります。

このDDLを生成するためのツールとして、「Custom Storage Space」ツールを提供しています。 このツールで生成されたDDLをデータベースに反映すれば、独自のStorageSpaceが利用できるようになります。

ツールの利用方法は Custom Storage Spaceを参照してください。

5.3. カラムマッピング

Entityのプロパティ定義では、 Store Col Name という属性を指定することができます。
この機能は、StorageSpaceに紐づく obj_store テーブルに独自のカラムを定義することで、そのカラムにプロパティ値を保存する機能です。

この値が未指定の場合は、プロパティの型とStorageSpace定義をもとにして基盤内部で「Property値格納汎用カラム」に自動的に値を格納します。 言いかえれば、 Store Col Name が未指定の場合は、どのカラムにデータが格納されているかはアプリ側では判断できません。

カラムマッピング機能により

  • 汎用カラムの文字列型は「TEXT」(MySQLの場合)として定義しているが、 独自のカラムでは「VARCHAR(3)」として定義することで、テーブルスペースを効率的に利用できる。

  • 独自カラムを指定することで、 obj_store のどのカラムに値が格納されるかが判断できる。
    例えば複合Indexを作成したり、Partitionを作成する際のKEYとして指定することができるなど、RDBネイティブの機能が利用できる。
    (年度カラムを定義して、テナント+年度などでPartitionを分けるなど)

といったことが可能になります。

極端な例としては、
あるEntityに特化したStorageSpaceを作成して、全てのプロパティに対して独自カラムを作成して、 プロパティで Store Col Name を定義すれば、「システム共通項目(変更不可)」以外は不要になります。

obj_store に対して独自のカラムを作成する場合は、 「カスタマイズ」で説明した手順を実施して作成されたDDLに対して追加してください。

以下の点に注意してください。

  • カラムの追加が必要なのは obj_storeobj_store_rb (削除データ格納用)テーブルの2つです。
    このテーブルのカラムは同期している必要があります。(データを物理削除するのみの場合はrbは利用されません)

  • 独自で追加するカラムの名前には、「STR_1」「NUM_1」「TS_1」「DBL_1」など、基盤が自動割当てに利用する名前は利用しないでください。

  • 多重度を1より大きい値に設定した場合は、設定値にあわせて複数の独自カラムを定義してください。
    例えば、Store Col Name「COL」で多重度「2」の場合、「COL_0」「COL_1」の独自カラムを定義 (連番は0から開始)

5.4. 疑似パーティション

通常 StorageSpace は 1 StorageSpace 1 テーブルセットの構成です。
疑似パーティションを設定することで 1 StorageSpace を複数テーブルセットで構成することが可能です。

entity_storagespace_pseudo_partition
Figure 1. 通常StorageSpaceと疑似パーティションを構成したStorageSpaceのテーブル構成イメージ
特徴

疑似パーティションは以下のような特徴があります。

  1. テーブルセットのテーブル名の接尾辞として、最後に __n という連番が付与されます。

    1. 0番目のテーブルには連番の接尾辞は付与されません。1番目のテーブルから連番が付与されます。

    2. tableNamePostfix が PS, tableCount が 3 を指定された場合の obj_store テーブルは obj_store__PS, obj_store__PS__1, obj_store__PS__2 の3テーブルを利用します。

    3. テーブル構造で説明されている全テーブルを、同様のネーミングで定義し作成します。

  2. 疑似パーティションが構成されている StorageSpace に Entity を定義した場合、レコードは決定した疑似パーティション位置へデータが格納されます。

    1. レコードを格納するテーブルを obj_store__PS__1 に決定したら、当該 Entity のレコードは全て同一テーブルに格納されます。(複数の疑似パーティションに跨ることはありません)

    2. unique, index テーブルに関しても、同様のネーミングルールのテーブルに格納されます。

      1. obj_store__PS__1obj_unique_str__PS__1obj_index_str__PS__1

    3. 疑似パーティション位置は TableAllocator により決定されます。詳細な説明は ServiceConfig - StoreService - TableAllocator を参照ください。

設定方法

service-config ファイルの storageSpace 設定に以下の設定を追加します。

疑似パーティションを定義するための設定サンプル
<!-- Entity Store Settings -->
<service>
  <interface>org.iplass.mtp.spi.datastore.StoreService</interface>

  <property name="dataStore" class="org.iplass.mtp.impl.datastore.grdb.GRdbDataStore">
    ・・・・
    <property name="storageSpace">
      <property name="storageSpaceName" value="partition_storage" />
      <property name="tableNamePostfix" value="PS" />
      <property name="tableCount"       value="3" /> (1)
      ・・・・・
    </property>
    ・・・・
  </property>
</service>
1 StorageSpace に設定する疑似パーティション数。本説明のように 3 を指定すると3つのテーブルセットで疑似パーティションが構成されます。
entity_storagespace_pseudo_partition_example
Figure 2. 疑似パーティションを定義するための設定サンプルのStorageSpaceとテーブル定義、Entity格納イメージ

設定後に対応するテーブルを作成する必要があります。テーブル定義は バッチツール - Custom Storage Space で作成することができます。

5.5. StorageSpace変更時の注意点

Entity の StorageSpace を変更した場合、登録済のデータは変更後の StorageSpace に移動しません。
もし、登録済みのデータを変更後の StorageSpace へ移行する必要がある場合は、以下のいずれかの方法でデータ移行を行ってください。

データ Export / Import ツールを利用したデータ移行

AdminConsole のツール 「EntityExplorer」、「Packaging」の Export / Import 機能を利用することで、データを移行します。
以下の手順で作業を実施してください。

  1. 移行対象データの Export

  2. Export データの削除

    1. 変更前の StorageSpace にデータが残るため、削除を実施します。次のいずれかの方法で削除を実施します。

      1. Entity View からデータを削除

      2. AdminConsole - EntityExplorer からデータを削除

      3. バッチツール - Storage Space Cleaner でデータをクリア(データが大量にある場合に利用を推奨)

  3. Entity の StorageSpace を変更

  4. 移行対象データの Import

Storage Space Migration ツールを利用したデータ移行

バッチツール - Storage Space Migration を利用することで、StorageSpace の変更および、データ移行を同時に行います。
バッチツール内でメタデータを更新するため、起動中のサーバーはメタデータを再読み込みする必要があります。

6.1. 概要

全文検索とは、保存さたEntity内のプロパティの値への横断検索ができる機能です。

ただし、全文検索はリアルタイムでデータが反映されるわけではありません。ご注意ください。

iPLAssでは、Lucene、Elasticsearch(OpenSearch)、Solrという全文検索エンジンのいずれかを利用することが可能です。

Solr用機能は将来削除される予定です。代替として ElasticsearchFulltextSearchService(OpenSearchFulltextSearchService)を利用することを推奨します。

各エンジンの簡単な差は下記を参照してください。

Lucene Elasticsearch(OpenSearch) Solr(非推奨)

概要

Javaベースのオープンソースの全文検索ライブラリ。
iPLAssが稼働するAPサーバ内の同一VM上に組み込まれ動作。

Elasticsearch(OpenSearch)はLuceneをベースに開発されたオープンソースの全文検索エンジン。
Elasticsearch(OpenSearch)単体でサーバとして稼働する。

Luceneをベースに、管理画面やキャッシュ機構を取り入れた全文検索サーバ。Solr単体でWebアプリケーションとして稼働する。

データ保存先

APサーバのローカルストレージ
mtp-service-config.xmlに保存先フォルダを指定するだけで利用が可能。

Elasticsearch(OpenSearch)サーバ内
別途Elasticsearch(OpenSearch)サーバを構築する必要がある。(本資料は構築済みであることが前提)

Solrサーバ内
別途Solrサーバを構築する必要がある。(本資料は構築済みであることが前提)

Analyzer(※)の扱いやすさ

デフォルトで使えるAnalyzerを適用する場合は、とても簡単。(複数種類有)
ただし、カスタマイズを行う場合は、Javaファイルを作成する必要がある。

デフォルトで使えるAnalyzerを適用する場合は、とても簡単。(複数種類有)
カスタマイズを行う場合も基本mtp-service-config.xmlで設定するのみ。

Analyzerはないため、Tokenizer/Filterを個別に設定する必要がある。
ただし、カスタマイズも含め設定はXMLの更新だけ済むため、その後はSolrサーバの再起動のみで反映が可能。

Analyzer とは

全文検索では、以下の2種類のクラス(Tokenizer/Filter)を組み合わせて、文字の分割を行います。
Analyzerを利用することで、すでに決まったクラス・決まった順序で文字の組み合わせができるようになります。

  • Tokenizer
    検索対象値(Entityに登録されているデータ等)や検索文字列(検索キーワードとして入力された文字列)を、検索のための文書の最小要素(Token)へ分割するクラスです。
    検索結果にヒットする条件は、検索対象値と検索文字列それぞれのTokenが一致することとなるため、Tokenizerの指定により検索の使い勝手が変わります
    例えば、「関西国際空港」という文字列があったとします。指定するTokenizerにより生成されるTokenは、以下のパターン等に分かれます。

    • 「関西国際空港」
      (「関西国際空港」を1つの検索文字列として扱われます。この場合、検索文字列に「関西」と入力してもヒットしません)

    • 「関西」「国際」「空港」
      (意味のある文字列に分割します。これにより、「関西」、「国際」、「空港」のいずれかの入力でヒットします)

    • 「関西」「西国」「国際」「際空」「空港」「港」
      (左記のように2文字ずつに分割します。これにより、上記よりもヒットする文字列の数は多くなります)
      ※ただし「東京都庁」のような場合は、「京都」という検索文字列でもヒットする、などの意図しないヒットが発生しやすいです

  • Filter
    表記ゆれの補完や検索文字として適さない文字列の削除などを行うクラスです。
    例えば、Lucene側でいえば以下のようなFilterが存在します。

    • JapaneseKatakanaStemFilter
      4文字以上のカタカナの長音を除去します。「サーバー」は「サーバ」とも補完され、検索文字列にどちらを入力してもヒットします。

    • CJKWidthFilter
      半角カナは全角カナへ、全角英数は半角英数へ補完され、補完後の文字列でヒットするようになります。

6.2. FulltextSearchServiceの設定

全文検索を利用する場合、まずは設定ファイルにてFulltextSearchServiceの設定を行う必要があります。 Lucene、Elasticsearch、OpenSearch、Solrを利用する場合で設定内容が異なります。

Lucene設定

全文検索に関する設定をFulltextSearchServiceに設定します。 Indexファイルの保存場所、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。

次に設定ファイルの設定例を示します。

mtp-service-config.xmlの設定例(必要最低限の設定)

デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>

    <class>org.iplass.mtp.impl.fulltextsearch.lucene.LuceneFulltextSearchService</class> (1)
    <property name="useFulltextSearch" value="true" /> (2)
    <property name="directory" value="/lucene/indexDir" /> (3)
</service>
1 実装クラスとしてLuceneFulltextSearchServiceを指定します
2 全文検索機能を有効化する場合trueを指定します
3 Luceneのindexファイルを格納するルートディレクトリを指定します
mtp-service-config.xmlの設定例(主要な項目を設定)

主要な設定項目を設定した例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>

    <class>org.iplass.mtp.impl.fulltextsearch.lucene.LuceneFulltextSearchService</class>
    <property name="useFulltextSearch" value="true" />
    <property name="directory" value="/lucene/indexDir" />

    <property name="maxRows" value="1000" />
    <property name="throwExceptionWhenOverLimit" value="true"/>

    <property name="analyzerSetting" class="org.iplass.mtp.impl.fulltextsearch.lucene.JapaneseAnalyzerSetting">
        <property name="className" value="org.apache.lucene.analysis.ja.JapaneseAnalyzer" />
        <property name="mode" value="SEARCH" />
    </property>

</service>

各設定項目の概要を以下に説明します。

プロパティ名 内容説明

useFulltextSearch

全文検索機能を有効にする場合は true にします。

directory

indexファイルを保存するルートディレクトリを指定します。 このディレクトリ配下にテナント、Entity定義毎にindexファイルが作成されます。

maxRows

全文検索サーバから取得する検索結果の最大件数を設定します。

件数が1000件以上で、かつ、Oracleを利用する場合は、 Oracle設定の enableInPartitioning プロパティ値を true へ変更してください。

throwExceptionWhenOverLimit

false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。

下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。

FulltextSearch Lucene SearchResult False

true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。

FulltextSearch Lucene SearchResult True

binaryParser

BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。

analyzerSetting

利用するAnalyzerの設定を行います。 classには org.iplass.mtp.impl.fulltextsearch.lucene.SimpleAnalyzerSetting もしくはJapaneseAnalyzerの設定に特化した org.iplass.mtp.impl.fulltextsearch.lucene.JapaneseAnalyzerSetting を指定します。

SimpleAnalyzerSettingの場合、Analyzerのクラス名(className)を指定可能です。 JapaneseAnalyzerSettingの場合、加えてmode、userDictionaryなどの指定が可能です。

また、 Entity定義単位にAnalyzerを切り替えする場合には、 org.iplass.mtp.impl.fulltextsearch.lucene.PerEntityAnalyzerSetting を利用可能です。

また、 org.iplass.mtp.impl.fulltextsearch.luceneAnalyzerSetting を実装する独自のクラスを指定しカスタムのAnalyzerを利用することも可能です。

利用可能なAnalyzer

以下はLuceneが提供するAnalyzerです。 詳細はLuceneのドキュメントを参照ください。

  • org.apache.lucene.analysis.core.WhitespaceAnalyzer
    空白分割

  • org.apache.lucene.analysis.core.SimpleAnalyzer
    アルファベット分割

  • org.apache.lucene.analysis.core.StopAnalyzer
    ストップワード分割

  • org.apache.lucene.analysis.standard.StandardAnalyzer
    高度分割(Eメール・アドレス・頭字語・中国語・日本語・韓国語・英数字など)

  • org.apache.lucene.analysis.cjk.CJKAnalyzer
    Bi-gram分割(文章が分かち書きされない言語である中国語、日本語および韓国語向け)

  • org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer
    中国語分割(簡体字中国語または中国語と英語が混在している文字列に有効)

  • org.apache.lucene.analysis.ja.JapaneseAnalyzer
    日本語分割(Searchモード):形態素解析しつつ、複合語で構成された単語を適切に分割します。

Elasticsearch設定

全文検索に関する設定をFulltextSearchServiceに設定します。 サーバURL、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。

次に設定ファイルの設定例を示します。

mtp-service-config.xmlの設定例(必要最低限の設定)

デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>

    <class>org.iplass.mtp.impl.fulltextsearch.elasticsearch.ElasticsearchFulltextSearchService</class> (1)
    <property name="useFulltextSearch" value="true" /> (2)
    <property name="restClientFactory"  class="org.iplass.mtp.impl.fulltextsearch.elasticsearch.DefaultRestClientFactory">
        <property name="elasticsearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/> (3)
    </property>
</service>
1 実装クラスとしてElasticsearchFulltextSearchServiceを指定します
2 全文検索機能を有効化する場合trueを指定します
3 ElasticsearchのサーバURLを指定します
mtp-service-config.xmlの設定例(主要な項目を設定)

主要な設定項目を設定した例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>
    <class>org.iplass.mtp.impl.fulltextsearch.elasticsearch.ElasticsearchFulltextSearchService</class>
    <property name="useFulltextSearch" value="true" />
    <property name="restClientFactory"  class="org.iplass.mtp.impl.fulltextsearch.elasticsearch.DefaultRestClientFactory">
        <property name="elasticsearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/>
    </property>

    <property name="maxRows" value="1000" />
    <property name="throwExceptionWhenOverLimit" value="true"/>

    <property name="analysisFactory" class="org.iplass.mtp.impl.fulltextsearch.elasticsearch.analysis.DefaultAnalysisFactory">
        <property name="analyzer" >
            <property name="my_kuromoji" class="org.iplass.mtp.impl.fulltextsearch.elasticsearch.analysis.analyzer.KuromojiAnalyzerFactory">
                <property name="mode" value="Search"/>
                <property name="method" value="Nfc"/>
            </property>
        </property>
    </property>
    <property name="defaultAnalyzerProperty" >
        <property name="analyzer" value="kuromoji"/>
    </property>
    <property name="analyzerPropertyPerEntity" >
        <property name="testEntity" class="org.iplass.mtp.impl.fulltextsearch.elasticsearch.mappings.AnalyzerProperty">
            <property name="analyzer" value="my_kuromoji"/>
        </property>
    </property>

</service>

各設定項目の概要を以下に説明します。

プロパティ名 内容説明

useFulltextSearch

全文検索機能を有効にする場合は true にします。

elasticsearchUrl

ElasticsearchのサーバURLを指定します。

maxRows

全文検索サーバから取得する検索結果の最大件数を設定します。

件数が1000件以上で、かつ、Oracleを利用する場合は、 Oracle設定の enableInPartitioning プロパティ値を true へ変更してください。

throwExceptionWhenOverLimit

false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。

下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。

FulltextSearch Lucene SearchResult False

true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。

FulltextSearch Lucene SearchResult True

binaryParser

BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。

analysisFactory

カスタムでAnalyzer等を定義したい場合に利用します。 classには org.iplass.mtp.impl.fulltextsearch.elasticsearch.analysis.DefaultAnalysisFactory を指定します。

defaultAnalyzerProperty

デフォルトで利用するAnalyzer名を指定します。 classには org.iplass.mtp.impl.fulltextsearch.elasticsearch.mapping.AnalyzerProperty を指定します。Analyzer名にはデフォルトで提供されているAnalyzerやカスタムで定義したAnalyzerを指定することができます。
デフォルトで提供されているAnalyzerについては、Elasticsearchのドキュメントを参照してください。

analyzerPropertyPerEntity

Entity定義単位でAnalyzerを切り替えたい場合、Entity名とAnalyzerPropertyをMap形式で指定します。

OpenSearch設定

全文検索に関する設定をFulltextSearchServiceに設定します。 サーバURL、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。

次に設定ファイルの設定例を示します。

mtp-service-config.xmlの設定例(必要最低限の設定)

デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>

    <class>org.iplass.mtp.impl.aws.fulltextsearch.opensearch.OpenSearchFulltextSearchService/class> (1)
    <property name="useFulltextSearch" value="true" /> (2)
    <property name="restClientFactory"  class="org.iplass.mtp.impl.aws.fulltextsearch.opensearch.DefaultRestClientFactory">
        <property name="openSearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/> (3)
    </property>
</service>
1 実装クラスとしてOpenSearchFulltextSearchServiceを指定します
2 全文検索機能を有効化する場合trueを指定します
3 OpenSearchのサーバURLを指定します
mtp-service-config.xmlの設定例(主要な項目を設定)

主要な設定項目を設定した例を以下に示します。

<service>
    <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>
    <class>org.iplass.mtp.impl.aws.fulltextsearch.opensearch.OpenSearchFulltextSearchService</class>
    <property name="useFulltextSearch" value="true" />
    <property name="restClientFactory" class="org.iplass.mtp.impl.aws.fulltextsearch.opensearch.DefaultRestClientFactory" >
        <property name="openSearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/>
        <property name="httpRequestInterceptorFactory" class="org.iplass.mtp.impl.aws.AWSRequestSigningApacheInterceptorFactory" >
            <property name="serviceName" value="es"/>
            <property name="region" value="ap-northeast-1"/>
        </property>
    </property>

    <property name="analysisFactory" class="org.iplass.mtp.impl.aws.fulltextsearch.opensearch.analysis.DefaultAnalysisFactory">
        <property name="analyzer" >
            <property name="my_kuromoji" class="org.iplass.mtp.impl.aws.fulltextsearch.opensearch.analysis.analyzer.KuromojiAnalyzerFactory">
                <property name="mode" value="Search"/>
                <property name="method" value="Nfc"/>
            </property>
        </property>
    </property>
    <property name="defaultAnalyzerProperty" >
        <property name="analyzer" value="kuromoji"/>
    </property>
    <property name="analyzerPropertyPerEntity" >
        <property name="testEntity" class="org.iplass.mtp.impl.aws.fulltextsearch.opensearch.mappings.AnalyzerProperty">
            <property name="analyzer" value="my_kuromoji"/>
        </property>
    </property>

</service>

各設定項目の概要を以下に説明します。

プロパティ名 内容説明

useFulltextSearch

全文検索機能を有効にする場合は true にします。

openSearchUrl

OpenSearchのサーバURLを指定します。

httpRequestInterceptorFactory

httpRequestInterceptorを生成するFactoryクラスを設定します。 BASIC認証ではなく、IAM認証情報を使用してリクエストを署名したい場合、実装クラスである org.iplass.mtp.impl.aws.AWSRequestSigningApacheInterceptorFactory を指定します。

maxRows

全文検索サーバから取得する検索結果の最大件数を設定します。

件数が1000件以上で、かつ、Oracleを利用する場合は、 Oracle設定の enableInPartitioning プロパティ値を true へ変更してください。

throwExceptionWhenOverLimit

false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。

下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。

FulltextSearch Lucene SearchResult False

true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。

FulltextSearch Lucene SearchResult True

binaryParser

BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。

analysisFactory

カスタムでAnalyzer等を定義したい場合に利用します。 classには org.iplass.mtp.impl.aws.fulltextsearch.opensearch.analysis.DefaultAnalysisFactory を指定します。

defaultAnalyzerProperty

デフォルトで利用するAnalyzer名を指定します。 classには org.iplass.mtp.impl.aws.fulltextsearch.opensearch.mappings.AnalyzerProperty を指定します。Analyzer名にはデフォルトで提供されているAnalyzerやカスタムで定義したAnalyzerを指定することができます。
デフォルトで提供されているAnalyzerについては、OpenSearchのドキュメントを参照してください。

analyzerPropertyPerEntity

Entity定義単位でAnalyzerを切り替えたい場合、Entity名とAnalyzerPropertyをMap形式で指定します。

Solr設定

Solr用機能は将来削除される予定です。代替として ElasticsearchFulltextSearchService(OpenSearchFulltextSearchService)を利用することを推奨します。
  1. mtp-service-config.xmlの設定
    下記設定を確認してください。

    <!-- 全文検索で利用するService -->
    <service>
      <interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>
      <property name="useFulltextSearch" value="true" />
      <property name="maxRows" value="10" />
      <property name="throwExceptionWhenOverLimit" value="false"/>
    
      <!-- solr利用 -->
      <class>org.iplass.mtp.impl.fulltextsearch.FulltextSearchSolrService</class>
      <property name="solrUrl" value="http://{ADDRESS}:{PORT}/solr/{CoreName}/" />
    </service>
    プロパティ名 内容説明

    useFulltextSearch

    全文検索機能を有効にする場合は true にします。

    maxRows

    全文検索サーバから取得する検索結果の最大件数を設定します。

    件数が1000件以上で、かつ、Oracleを利用する場合は、Oracle設定の enableInPartitioning プロパティ値を true へ変更してください。

    throwExceptionWhenOverLimit

    false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。

    下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。

    FulltextSearch Solr SearchResult False

    true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。

    FulltextSearch Solr SearchResult True

    solrUrl

    利用するSolrサーバのURL

  2. schema.xmlの設定

    有償版のSDKに同梱されている iplass-ee-solr-XXX.jar ファイルを解凍し、schema\solr ディレクトリ下の schema.xml を取得します。

    schema.xmlは、検索対象値の保持方法や分割方法の情報が定義されています。
    対象ファイルはサーバ構築時に作成されたcore(以下の画像であれば、「collection1」)/confの下に配置するファイルとなります。

    FulltextSearch Solr SchemaXML Setting

    下記はschema.xmlの一部抜粋したものになります。

    <?xml version="1.0" encoding="UTF-8" ?>
    <schema name="iPLAss" version="1.4">
        :
        :
        <fieldType name="text_sen" class="solr.TextField" positionIncrementGap="100" > (1)
            <analyzer> (2)
                <charFilter class="solr.MappingCharFilterFactory" mapping="lang/mapping_ja.txt"/> (3)
                <tokenizer class="solr.JapaneseTokenizerFactory" mode="SEARCH" discardPunctuation="true" />
                <filter class="solr.JapaneseBaseFormFilterFactory"/>
                <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
                <filter class="solr.CJKWidthFilterFactory"/>
                <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />
                <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
                <filter class="solr.LowerCaseFilterFactory"/>
                <filter class="solr.SynonymFilterFactory" synonyms="lang/synonyms_ja.txt" ignoreCase="true" expand="true"/>
            </analyzer>
        </fieldType>
        :
        :
        <fields>
            <field name="V_1" type="text_sen" indexed="true" stored="true" omitNorms="true" multiValued="true" /> (1)
            <field name="V_2" type="text_sen" indexed="true" stored="true" omitNorms="true" multiValued="true" />
        </fields>
    </schema>
    1 この紐付きが一致するプロパティに対して、上記で定義したTokenizer/Filterが適用されます。
    フィールドごとに変更した場合は、別途fieldTypeを作成し紐付けるようにしていただくことで実現可能になります。
    2 この部分をカスタマイズすることで、任意のTokenizer/Filterを組み合わせて全文検索を利用することができます。
    3 サーバ構築時に作成されたcoreのinstanceDirの conf/lang ディレクトリの下にTokenizer/Filterに適用するxxx.txtファイルを入れます。

    ※サンプル定義: LuceneのデフォルトAnalyzerである org.apache.lucene.analysis.ja.JapaneseAnalyzer をSolrで類似実現する場合の定義例
    (charFilterのクラスは org.apache.lucene.analysis.ja.JapaneseAnalyzer にはない)
    (xxx.txt類は各自用意したものを想定)

    その他利用できるclass値についてはSolrのドキュメントを参照ください。

    ※Lucene側のAPIに関しては、xxxxFactoryというものがSolrで設定できるクラスとなっております。

    StopAnalyzer

    Luceneで指定できるAnalyzer

    StopFilter

    Luceneで指定できるFilter

    StopFilterFactory

    Solrで指定できるFilter

    <fieldType>タグ内の各タグについて

    • <analyzer>タグ
      Tokenizer/Filterを定義するための親タグです。
      また以下のように定義することも可能です。

      <analyzer type="index"> 検索対象値を保持する前に適用されるTokenizer/Filterの定義します。
          ・・・・
      </analyzer>
      <analyzer type="query"> 検索文字列を検索対象値と比較する前に適用されるTokenizer/Filterを定義します。
          ・・・・
      </analyzer>
    • <charFilter>タグ
      Tokenizer実行前に呼ばれるFilterを定義します。

    • <tokenizer>タグ
      実行するTokenizerを定義します。

    • <filter>タグ
      Tokenizer実行後に呼ばれるFilterを定義します。

class値以外の要素(modeやtagsなど)は指定するclassにより異なりますので、ご注意ください。
  • Solrサーバに関する補足
    Tokenizer/FilterはSolrサーバ本体だけでは動作しないものがあります。
    例えば、schema.xmlに以下の定義がある場合、

        :
        :
        <fieldType name="text_chinese" class="solr.TextField">
            <analyzer>
                <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
                <filter class="solr.LowerCaseFilterFactory" />
            </analyzer>
        </fieldType>
        :
        :

    この場合は、サーバ構築時に作成されたcoreのinstanceDir(以下の画像であれば、「collection1」)下に lib ディレクトリを作成し、そのディレクトリにjarを追加で配置してください。

    FulltextSearch Solr Lib

    また、検索条件を AND とするため <サーバ構築時に作成されたcore>/conf/solrconfig.xml に次の設定を行ってください。

        :
        <initParams path="/update/**,/query,/select,/spell">
            <lst name="defaults">
                ・・・・
                <str name="q.op">AND</str>
            </lst>
        </initParams>
        :

    デフォルトの検索条件は OR です。検索条件を OR とする場合は上記設定は不要です。

6.3. 利用方法

Indexの設定

AdminConsoleからIndex対象とするEntity、および、Entityの列の設定をします。
全文検索対象としたいEntityを開き、「crawl for full text search」にチェックしてください。 すると、デフォルトでIndex対象となりうるプロパティの「Crawl」列にチェックが出ます。 各プロジェクトで必要なプロパティに対してのみチェックがあることを確認し、保存してください。

typeがBinaryであるプロパティクを全文検索対象とした場合、バイナリのファイル名 + " " + バイナリのファイルタイプ という値で登録されます。
FulltextSearch Index Setting

Indexの作成

全文検索で検索が行われるデータは下記のIndex作成をした時点でのデータとなります。(ただし取得(表示)されるデータは、検索時点の最新データとなります)
そのため、新しく登録したデータをIndexに含めたいなどの場合は、必ずIndexの再作成を実施してください。

  1. AdminConsoleから
    AdminConsole画面の左下メニューにあるToolsのEntityExplorerを選択します。
    全文検索を利用する設定になっている場合、「Entity Crawl」タブが表示されます。
    「Entity Crawl」タブのリストには「crawl for full text search」にチェックをつけたEntityのみが表示されます。

    FulltextSearch Index Create AdminConsole

    クローリングには選択したEntityのみを対象に実施する方法と、全Entityを全てクローリングする2種類があります。

    A.

    任意のEntityのみを対象としてクローリングしたい場合はリストのEntityにチェックをいれ、Start Crawl ボタンをクリックして下さい。

    B.

    クローリング対象Entityを全てクローリングしたい場合は Re Crawl All Entity ボタンをクリックして下さい。この場合、チェックをいれていないEntityも全てが対象となります。

    FulltextSearch Index Create Crawl
    C.

    クローリング処理が完了しましたら、INDEXデータの変更を反映させるために、Refresh ボタンをクリックしてください。

  2. バッチから
    iPLAss SDKで配布している crawl_entity.bat(sh) をクーロン等にセットすることで、バッチ起動が可能です。
    バッチの詳細についてはEntity Crawlを参照してください。

検索機能

画面からの検索

全文検索機能を有効にしている場合のみ画面上部に拡大鏡マークが表示されます。 拡大鏡マークをクリックすると、検索プルダウンが表示されます。 また、このプルダウンに表示されるエンティティはAdminConsoleでIndex対象としたEntityのみとなります。 プルダウン右にあるテキストボックスに文字列を入力して検索することで全文検索が実行されます。 エンティティを選択しない場合はIndex対象とした全Entityが対象なり、下記のような検索結果画面となります。

FulltextSearch Search
(参考)ソートについて

全文検索機能でのソートは以下のようになっています。

第1ソート:スコア(降順)
第2ソート:Entity定義名(昇順)

スコアとは、検索文字列と検索対象値(行単位)の関連度が数値化されたものとなります。 これらはSolr/Lucene内部で算出された値を利用しています。 簡単に条件を表すと、以下に一致すればするほどスコア値が高くなる傾向があります。

  • 検索文字列の単語がより多く含まれている

  • 検索対象の値が短い

  • 全検索対象の中で希少単語が含まれている

「検索対象の値が短い」の例:

実行環境として、全文検索の取得上限(maxRows設定)を 5 に設定し、 java という文字列が3つ出てくる情報を4つ、2つ出てくる情報(緑枠の部分)を3つ用意している状態です。 (全文検索対象のプロパティは「検索対象1」~「検索対象3」)

スコア値が高くなる傾向の1つである「検索文字列の単語がより多く含まれている」が適用されたことにより、 java という文字列が2つ出てくる情報は1件分しか表示できません。
java という文字列が2つ出てくる情報の種類として、1件はプロパティに設定した値が java だけのもののみ、 その他2件は java の他に文字列を含んでいる値になっています。
「検索対象の値が短い」という条件が適用されたことにより、 java だけ登録した値がスコアとして高くなり、 全文検索結果として表示されています。

FulltextSearch SearchTargetValue Short
ロジックからの検索

ロジックから検索する方法は2種類あります。

  1. 全エンティティを対象に検索する場合
    EntityManagerのfulltextSearchEntityを利用して下さい。複数のEntityに対して横断的に一括で検索します。 ただし、取得できるデータはEntity毎にマージされたものとなります。

  2. EQLの検索条件として全文検索条件を利用する場合
    下記のようにEQLの条件中に、全文検索の条件を含めることが可能です。Containsの中に検索キーワードをセットして下さい。 EQLを利用し検索する場合は、当該Entityに対して設定されているセキュリティ権限が反映されます。

    Containsの中に検索キーワードをセットして下さい。

    EntityManager em = ManagerLocator.manager(EntityManager.class);
    
    Query query = new Query();
    query.select(Entity.OID, Entity.NAME).from("search.Test01").where(new Contains("hogehoge"));
    
    SearchResult<Entity> result = em.searchEntity(query);

    もしくはEQL直接以下のように利用可能です。

    EntityManager em = ManagerLocator.manager(EntityManager.class);
    
    SearchResult<Entity> result = em.searchEntity(Query.newQuery("select oid, name from search.Test01 where contains ('test')"));

画面のカスタマイズ

検索結果および詳細などのView設定

全文検索結果に表示されるプロパティや[詳細、編集]リンク押下時の遷移先ViewをAdminConsoleから設定することが可能です。
まず、対象のEntity毎に全文検索結果に表示したい項目などを設定したViewをSearch Layoutで作成してください。 その後、AdminConsole画面のMetaDataSettings内にある View Components > TopView の設定を変更します。

TopViewの機能概要、作成方法についてはTopViewの章を参照してください。

右にあるメニューから、 Toolbar Parts > Fulltext Search(PU) を選択し、Main Area(Droppable P(Parts))にドラッグ&ドロップしてください。

FulltextSearch SetParts

ドラッグ&ドロップして出てきたFulltext Searchの設定ボタンをクリックすると、 crawl for full text search にチェックをつけたEntityのみが表示されます。
Entity View列に設定したSearchViewを使用して、全文検索結果となったEntityの情報を表示します。

別途対象EntityのSearch ViewでカスタマイズしたViewを作成することで、Entity Viewの選択リストに表示されるようになります。
FulltextSearch Parts Setting

その他の設定可能な項目は以下になります。

設定項目 設定内容

Display search textbox

本項目にチェックを入れると、ヘッダーに全文検索用のテキストボックスが表示されます。

Display user name in privileged execution

本項目にチェックを入れると、UserPropertyEditorが設定されているプロパティに対し、ユーザー情報のEntity、またはユーザー名のプロパティに参照権限が無いユーザーでも、特権実行をしてユーザー名を表示することができます。

Entity View

全文検索の結果表示で利用するViewを選択します。

show in search list

本項目にチェックを入れると、全文検索実行時の対象として、個別に選択が可能になります。

詳細・編集リンクのカスタマイズ

全文検索結果を表示するSearchViewのSearchFormView Settingに自作したアクションを設定することで、 カスタマイズした画面への遷移が可能となります。

FulltextSearch Customize
  1. 詳細リンク先アクション

  2. 編集リンク先アクション

遷移先で取得可能なリクエスト情報は以下です。

パラメータ名 内容説明

defName

選択した情報のEntity定義名

oid

選択した情報のOID

version

選択した情報のVersion