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)を参照してください。
また、 マテリアルデザインに準拠したデータ操作画面(Material Design Components、通称:MDC) を提供します。 MDCはレスポンシブなデザインを特徴としています。
詳細はMDC(Material 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が定義されています。
名前 | 表示名 | データ型 | 内容 |
---|---|---|---|
オブジェクトID |
String |
レコードを一意に特定するID。変更不可。 |
|
名前 |
String |
レコードを表すラベル。必須項目。値はユニークである必要はありません。 |
|
説明 |
String |
レコードの説明。任意項目。 |
オブジェクトID (oid)
Entityデータは1レコード単位に oid
という一意のKEY値を保持します。
標準の動作として、oid
はEntityデータの登録時に自動的に採番されます。
更新処理で変更することはできません。
後述するEntityどうしの参照定義(Reference Property)においても、
この oid
で参照関係を保持します(正確には oid
+ version
です)。
標準で自動採番される 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 |
データ作成者。作成者に該当する |
updateBy |
更新者 |
String |
データ更新者。更新者に該当する |
lockedBy |
ロックユーザー |
String |
データロック機能用。ロック者に該当する |
システムPropertyは制御用としてiPLAss内部で制御されるため、 各アプリケーションで独自の用途として値を格納したりしないでください。 バージョンアップなどで増減したり、格納される値が変更される可能性があります。
startDate
や endDate
についても、「ユーザー」「おしらせ情報」Entityなどで一部利用していますが、
Entityの バージョン管理設定 により利用される可能性があるため、基本的には利用できません。
2.3. Propertyの設定
Entityに対して、保存したいデータ項目に合わせたPropertyを追加していきます。
Entityに対するより高度な設定については 高度な設定 で説明します。
Propertyの作成
Propertyを作る際は、格納する値の型に特化したデータ型の選択や、必須項目や長さなどの制約条件の設定を行います。
Propertyを追加する場合は Add
ボタン、編集する場合は対象のPropertyレコードをダブルクリック、
削除する場合は対象のPropertyを選択(ShiftやCtrlで複数可)して Remove
ボタンをクリックします。
またPropertyの順番を並び替える場合はドラッグ&ドロップで並び替えてください。
Propertyの詳細設定
Propertyは次の項目を設定可能です。 また指定したPropertyのデータ型によって、設定する項目が変更されます (一部データ型により変更できない項目があります)。
設定項目 | 設定内容 |
---|---|
Name |
物理名を指定します。英数字のみ指定可能です。 |
Display Name |
表示名を指定します。 |
データ型を指定します。 |
|
多重度を指定します。 |
|
Required |
必須項目かを指定します。 |
CanEdit |
値を変更できるかを指定します。 |
インデックスを指定します。 |
|
暗号化有無、および形式を指定します。 |
|
検証ロジックを指定します。 |
|
正規化ロジックを指定します。 |
データ型の指定
提供されているPropertyのデータ型です。基本的な型とiPLAssに特化した特殊な型があります。
型 | 説明 | Java型 | ||
---|---|---|---|---|
String |
文字列型です。 |
String |
||
Boolean |
真・偽を表す型です。 |
Boolean |
||
Integer |
整数を表す数値型です。 |
|||
Float |
小数を表す数値型です。 |
Double |
||
Decimal |
正確な小数計算を扱う数値型です。
|
BigDecimal |
||
DateTime |
日付と時間を表す型です。 |
java.sql.Timestamp |
||
Date |
日付を表す型です。 |
java.sql.Date |
||
Time |
時間を表す型です。 |
java.sql.Time |
型 | 説明 | Java型 |
---|---|---|
選択値として「値とラベル」のセットを定義することができる型です。 |
org.iplass.mtp.entity.SelectValue |
|
自動採番値を扱う型です。 |
String |
|
式を設定することができる型です。 |
String |
|
バイナリデータを扱う型です。(BLOB型) |
org.iplass.mtp.entity.BinaryReference |
|
String型では入りきらない文字列を扱う型です。(BLOB型) |
String |
|
各エンティティを関連付ける事ができる型です。 |
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に対して提供されているその他の機能について説明します。
設定項目 | 設定内容 |
---|---|
|
|
Entityデータのバージョン管理方式を指定します。 |
|
Entityデータの格納先を指定します。 |
|
EntityデータのCRUD操作に対するログを記録するかを指定します。 |
|
全文検索機能用のINDEXを作成するかを指定します。 |
|
Entityの検索結果をキャッシュするかを指定します。 |
|
CommandなどでEntity操作を行う際に、Javaで実装されたEntityクラスを利用する場合に指定します。 |
|
EntityのEventListenerを指定します。 |
|
Entityデータの国際化対応を指定します。 |
共通Propertyの変更
oid
と name
については他のPropertyを指定することで代用することができます。
oid Propertyの変更
外部システムからのデータ取り込みや、IDとしてユーザーにわかりやすい値にしたい場合など、
oid
として利用するPropertyを変更することが可能です。
Admin Consoleで oid
を指定する場合は、「OID」列で指定してください。
以下の属性のPropertyのみ oid
として指定することが可能です。
-
型が 基本型 または AutoNumber である
-
必須項目である
-
変更不可である
-
多重度が1である
複数のPropertyを指定することが可能です。
この場合、 oid
に格納される値は、選択したPropertyを上から順番にハイフン「-」で
結合した値になります。
既に登録済みのEntityデータが存在する状態で oid
Propertyを変更した場合、
登録済みのデータは自動的には変更されません。
このような場合は、Entityデータのエクスポート/インポートなどによりデータを手動で変更する必要があります。
name Propertyの変更
oid
同様、 name
も対象とするPropertyを変更することが可能です。
Admin Consoleで変更する場合は、「Name」列で指定してください。
以下の属性のPropertyのみ name
として指定することが可能です。
-
型が 基本型 、 AutoNumber 、 Select のいずれかである
-
必須項目である
-
多重度が1である
oid
と異なり、複数のPropertyを指定することはできません。
name
を指定した場合には、以下の点について考慮する必要があります。
-
登録時の動作
name
Propertyを独自に設定した場合、Entityデータの更新時にname
に同じ値が設定されます(name
Propertyがなくなるわけではありません)。 例えば、name
Propertyと、独自に指定したPropertyそれぞれに値を設定して更新した場合、name
に設定された値は上書きされます。 -
汎用画面(GEM)のカスタマイズが必要
汎用画面では、標準でname
とdescription
Propertyが検索・詳細画面上に表示されます。name
Propertyを独自に設定した場合は、name
を削除し独自Propertyを追加するなど、汎用画面のレイアウト調整が必要です。
既に登録済みのEntityデータが存在する状態で name
Propertyを変更した場合、
登録済みのデータは自動的には変更されません。
例えば、必須ではない項目を必須に変更して name
に指定した場合も、
登録済のデータは値が設定されていない可能性がある状態になってしまいます。このようなデータは最初の更新時にエラーになります。
この場合は、Entityデータのエクスポート/インポートなどにより登録済みデータを手動でメンテナンスする必要があります。
作成したいEntityに name
に該当するPropertyがない場合は、 AutoNumber 型のPropertyを作成して、それを name
として指定してください。
データのバージョン管理
Entityの1レコードに対して、複数のバージョンを保持することができます。
バージョン管理を利用することで、修正履歴を保持できたり、先日付データを事前に登録することが可能になります。
バージョン管理する場合、Entityに定義される共通プロパティ version
、 state
、 startDate
、 endDate
が利用され、現在有効なバージョンが決定されます。
version プロパティは排他制御のためのものではありません。排他制御は updateDate プロパティでチェックしています。
|
EQLでバージョン管理されたEntityを検索する際、EQLの検索条件にバージョン管理項目を指定した場合、全てのバージョンのデータを検索対象とします。未指定の場合、現在有効なバージョンのデータのみを検索対象とします。 |
バージョン管理方式には以下の種類があります。
タイプ | 説明 |
---|---|
NONE |
バージョンデータを保持しません。データに対する最新の状態のみ保持されます。 |
NUMBER BASE |
共通Propertyの |
TIME BASE |
共通Propertyの |
SIMPLE TIME BASE |
共通Propertyの |
STATE BASE |
共通Propertyの |
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の startDate
、 endDate
(有効期間)を複数保持することが可能になります。
データを更新する際に有効期間を指定します。
検索処理で有効なデータは システム日時で有効期間に該当(startDate≦システム日時<endDate)し、且つ version
が最大、且つ state
が 有効
のものになります。
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 |
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の startDate
、 endDate
(有効期間)で有効なバージョンを制御します。SIMPLE TIME BASEは、TIME BASEとは異なり、複数バージョン間で有効期間が重なることは許可されません。
検索処理で有効なデータは システム日時で有効期間に該当(startDate≦システム日時<endDate)し、且つ state
が 有効
のものになります。
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) {
}
Entity間の連携を定義するためのReference型のPropertyが参照する参照先のバージョンは、 ReferencePropertyで指定した「バージョン管理」設定によって決定されます。
バージョン管理を行う場合、 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として実装するか、SendNotificationとしてメールやSMS、WebHookなどで通知することができます。
Entityのイベント
イベントは EntityManager
を経由したEntity操作時に発生します。
汎用画面でのEntity操作時にも、内部的に EntityManager
を利用しているためイベントが発生します。
以下に EntityManager
のメソッドとイベントの関連を示します。
EntityManager#method | イベント | 戻り値 | 説明 |
---|---|---|---|
load |
onLoad |
void |
ロード処理。 |
searchEntity |
onLoad |
void |
検索処理(Entity形式)。1件ごとに呼び出される |
validate |
beforeValidate |
void |
検証処理。 |
insert |
beforeValidate |
void |
登録処理。 |
update |
beforeValidate |
void |
更新処理。 |
delete |
beforeDelete |
boolean |
削除処理。 |
purge |
afterPurge |
void |
ごみ箱から、削除処理。 |
restore |
afterRestore |
void |
ごみ箱から、復活処理。 |
search 、 updateAll 、 deleteAll 時はイベントは発生しません。イベントの戻り値として boolean を返すものは、 false を返すと後続の処理を実行しません。update 、 delete 時など更新前のEntityが存在する状態で、各通知メソッドが呼び出される際の引き渡されるentityインスタンスは、
EntityManagerから各更新メソッド呼び出し時のEntityインスタンスがそのまま引き渡されたものです。
そのため、oid以外のプロパティ項目を保持していない場合もあることにご注意ください。
|
Javaクラスによる実装
JavaクラスとしてEventListenerを実装する場合は、 EntityEventListener
インターフェースを実装したクラスを作成します。
org.iplass.mtp.entity.EntityEventListener
設定項目 | 設定内容 |
---|---|
class name |
実装したクラスを指定します。 |
mapped by reference info is unnecessary for listener |
|
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 |
|
利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
entity |
対象のEntityデータ。 |
context |
EntityEventContext |
event |
発生したイベント種別。
|
user |
ユーザー情報。 |
date |
システム日時。 |
event
には発生したイベントのタイプが設定されています。
Script形式の場合、1つのListenerで複数のEventに対する処理を実装できるので、Eventごとに処理を分けたい場合の判断として利用します。
このような場合、EventごとにそれぞれListener定義することもできます。
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>)。
|
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
以降は別インスタンス)。
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処理時にはEntityEventContextに更新前のEntity情報がloadされてセットされます。 このload時に被参照Propertyを取得しないかを設定します。
true
の場合、更新前Entityのload処理で被参照Propertyを除外します。
(load時のLoadOptionを withMappedByReference=false
にして処理します)
被参照Propertyは更新対象のPropertyではないため、Listener内部の処理で参照する必要がないのであれば、除外することで処理を高速化できます。
beforeValidateを使ったバリデーションエラーの発生のさせ方
-
例外にしたい場合は基本的にはApplicaitonExceptionをスロー
ApplicaitonException
をスローした場合、ApplicaitonException
の引数に設定した例外メッセージがエラーメッセージとしてGEMやMDCの画面上に表示されます。
以下は、ApplicaitonException
をスローさせる場合のサンプルコードです。
@Override
public void beforeValidate(Entity entity, EntityEventContext context) {
// ここになんらかのチェック処理を設定
// チェック処理の結果、例外として処理する場合
throw new ApplicationException("画面に表示するエラーメッセージ");
}
ApplicaitonException
の引数で指定したメッセージが画面上部に表示されます。
GEM画面のエラーメッセージ表示例
MDC画面のエラーメッセージ表示例
-
項目ごとにエラーメッセージを画面表示させたい場合はEntityValidationExceptionをスロー
EntityValidationException
をスローした場合、 第2引数に設定した項目ごとのエラーメッセージのリストがGEMやMDCの画面上に表示されます。 第2引数にはValidateError型のリストに画面に表示するエラーメッセージを項目ごとに設定します。
以下は、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画面のエラーメッセージ表示例
MDC画面のエラーメッセージ表示例
SendNotificationでの通知
SendNotificationを利用することでEntityに対する操作時にMail/SMS/Push/Webhook通知の送信ができます。
設定項目 | 設定内容 |
---|---|
Notification type |
送信する通知のタイプです。必須項目。
|
Template |
通知のテンプレート定義。必須項目。 |
ResultHandlerImplClassName |
(Webhookを選択した場合)
|
Synchronous |
(Webhookを選択した場合) |
SendTogether |
(Push NotificationかMailを選択した場合) |
Destination |
通知先を指定。選択した
|
Notification condition |
送信する場合の条件スクリプト 。 |
events |
実行するイベントをしています。 複数指定した場合は、各イベントで同じスクリプトが実行されます。
|
mapped by reference info is unnecessary for listener |
|
利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
entity |
対象のEntityデータ。 |
context |
EntityEventContextを参照してください。 |
event |
発生したイベント種別。
|
user |
ユーザー情報。 |
date |
システム日時。 |
・通知のテンプレート定義で利用可能な変数
バインド変数 | 設定される値 |
---|---|
tenant |
テナント情報。 |
entity |
対象のEntityデータ。 |
context |
EntityEventContextを参照してください。 |
event |
発生したイベント種別。
|
user |
ユーザー情報。 |
date |
システム日時。 |
データの多言語化
Entityデータ自体に対する多言語設定が行えます。多言語設定は Data Localization
で指定します。
詳細については、 データの多言語化を参照してください。
2.5. 標準提供のEntity
標準で提供されるEntityについて説明します。
標準で提供される一部のEntityにはEventListenerが組み込まれているため、 それらのEntityデータのインポート時には、Listener処理の実行有無に注意が必要となります。 |
Entity名 | EE Only | 説明 | EventListenerの処理概要 |
---|---|---|---|
mtp.Information |
- |
ニュースなどのコンテンツの情報が格納されます。 |
有効終了日が未設定の場合に、「2099/12/31」を設定します。 |
mtp.auth.ActionPermission |
- |
Actionに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.EntityPermission |
- |
Entityに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.WebApiPermission |
- |
WebApiに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.CubePermission |
〇 |
Cubeに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.WorkflowPermission |
〇 |
Workflowに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.UserTaskPermission |
〇 |
UserTaskに対する権限の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.Role |
- |
ロールに付与された各権限やロール割り当て条件の参照情報などを含みます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.RoleCondition |
- |
ロールに適用する条件の情報が格納されます。 |
権限情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.Group |
- |
ユーザーに設定可能なグループの情報が格納されます。親グループが指定でき、階層で表現することが可能です。 |
グループ情報は処理高速化のためにAPサーバにキャッシュされます。EventListenerの処理ではそのキャッシュの生成・破棄に関する処理が実装されています。 |
mtp.auth.Rank |
- |
ユーザーに設定可能なランク(会員種別など)の情報が格納されます。 |
- |
mtp.auth.User |
- |
ユーザーの情報が格納されます。姓や名などのユーザー属性に関する項目とアカウントポリシーなどの認証に関する項目を含みます。 |
|
mtp.maintenance.MetaDataTag |
- |
MetaDataExplorerを使用してインポートする際にローカルメタデータのTagの情報が一時的に格納されます。 |
- |
mtp.maintenance.Package |
- |
Packaging機能で設定したPackageの情報が格納されます。 |
- |
mtp.auth.oidc.OpenIdProviderAccount |
- |
OpenIDプロバイダのアカウントの情報が格納されます。アカウントに紐づくiPLAssのユーザー情報を含みます。 |
|
mtp.auth.UserImpersonationPermission |
〇 |
代理ログイン機能で使用されます。権限を与えるユーザーと成り代わり可能なユーザーがセットで格納されます。 |
- |
mtp.listing.SavedList |
〇 |
汎用検索や定型集計・簡易BIの検索条件やローデータが保存リストとして格納されます。 |
- |
mtp.listing.SavedListFolder |
〇 |
保存リストで設定したフォルダの情報が格納されます。 |
- |
mtp.scheduling.ScheduledTask |
〇 |
スケジューラ機能で使用されるスケジュールタスクの情報が格納されます。実行日時や実行結果などが含まれます。 |
|
mtp.scheduling.ScheduledTaskHistory |
〇 |
スケジューラ機能で使用されるスケジュールタスクの履歴情報が格納されます。ScheduledTask定義で |
- |
mtp.workflow.Assignment |
〇 |
ユーザータスクのユーザーへの割当情報が格納されます。 |
|
mtp.workflow.UserTask |
〇 |
ユーザータスクの情報が格納されます。 |
|
mtp.workflow.UserTaskQueue |
〇 |
ユーザータスクの割当ルールに |
- |
mtp.workflow.Workflow |
〇 |
現在のワークフローの状態が格納されます。 |
- |
mtp.workflow.ProcessHistory |
〇 |
ワークフローのNodeの |
- |
mtp.workflow.WorkflowTarget |
〇 |
ワークフロー対象の情報が格納されます。 |
- |
wam.auth.IdProviderAccount |
〇 |
IDプロバイダにおいて認証されたアカウント情報が格納されます。 |
|
wam.auth.UserSignUp |
〇 |
ユーザーの新規登録依頼内容が一時的に格納されます。 アクティベーション処理が完了した際に、iPLAssのユーザー情報に反映されます。 |
- |
wam.auth.VerificationRequest |
〇 |
メール、SMSなどでユーザーの本人確認(アクティベーション)をする際に検証情報が格納されます。 |
- |
wam.siteauth.CodeToken |
〇 |
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 Value と Local 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を設定した場合はゼロパディングされません。 採番値が固定桁数を超えた場合は、そのまま採番値が利用されます。 |
採番ルール |
採番する際のトランザクション制御を指定します。
|
書式 |
登録する値をGroovyTemplate形式で書式指定することができます。 |
書式設定
書式で利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
nextVal() |
次の採番された番号。最大桁数は18桁です。nextValの引数に採番単位とする |
yyyy |
年 |
MM |
月 |
dd |
日 |
HH |
時、24h表記 |
mm |
分 |
ss |
秒 |
date |
java.sql.Timestampのインスタンス |
entity |
登録対象のEntityデータ |
user |
登録者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に対して、 OID
や Unique 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の |
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の画面上に表示させるような場合は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型の検索
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の oid
と version
を保持します。
この参照関係を利用することで、参照元の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から参照される側(被参照)の場合に指定します。 |
参照先のバージョン |
参照先のデータとして取得するバージョンのポリシーを指定します。 |
ソート条件 |
この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の属性は親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を更新する処理が実行されることになります)
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型 |
---|---|---|
入力の有無を検証します。Propertyで設定する |
* |
|
文字列の長さを検証します。 |
String |
|
数値の範囲を検証します。 |
Number |
|
正規表現を利用して値を検証します。 |
String、Number |
|
バイナリのサイズを検証します。 |
BinaryReference |
|
バイナリのタイプを検証します。 |
BinaryReference |
|
Referenceの参照データの存在を検証します。 |
Entity |
|
GroovyScript書式で検証ロジックを実装します。 |
* |
|
Java Classで検証ロジックを実装します。 |
* |
対応するJava型以外のProperty型に対してValidatorを指定した場合、
検証時に EntityRuntimeException が発生します。Not Null Scripting Java Class 以外は、値が null の場合はチェックされません(true)。
|
NotNull
入力の有無を検証します。
AdminConsole上の編集画面では、Required
の設定と連動して追加、削除されます。
以下の場合にエラーとなります。
-
値が
null
-
String型の場合、値が空
-
配列の場合、サイズが0
すべての型で利用可能です。
NotNullに特化した設定項目はありません。
Length
文字列の長さを検証します。
以下の場合にエラーとなります。
-
checkBytes
がfalse
の場合、値の長さがmin
未満 -
checkBytes
がfalse
の場合、値の長さがmax
より上 -
checkBytes
がtrue
の場合、値のバイト数がmin
未満 -
checkBytes
がtrue
の場合、値のバイト数がmax
より上
String型で利用可能です。
設定項目 | 設定内容 |
---|---|
min |
最小値を指定します。 |
max |
最大値を指定します。 |
checkBytes |
バイト数でチェックする場合、trueにします。 |
Range
数値の範囲を検証します。
以下の場合にエラーとなります。
-
grater than min value
がtrue
の場合、値がmin
以下 -
grater than min value
がfalse
の場合、値がmin
未満 -
less than max value
がtrue
の場合、値がmax
以上 -
less than max value
がfalse
の場合、値がmax
より上
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]+
String型、Number型で利用可能です。
Number型の場合、 toString()
した値に対して検証します。
Number型に対応するPropertyタイプは Integer
Float
Decimal
です。
設定項目 | 設定内容 |
---|---|
pattern |
正規表現式を指定します。 |
BinarySize
バイナリのサイズを検証します。
以下の場合にエラーとなります。
-
バイナリのサイズが
min
未満 -
バイナリのサイズが
max
より上
BinaryReference型で利用可能です。
設定項目 | 設定内容 |
---|---|
min |
最小値(byte)を指定します。 |
max |
最大値(byte)を指定します。 |
BinaryType
バイナリのタイプを検証します。
以下の場合にエラーとなります。
-
バイナリのタイプが正規表現にマッチしない場合
BinaryReference型で利用可能です。
設定項目 | 設定内容 |
---|---|
acceptMimeTypesPattern |
mimeタイプを指定します(正規表現)。 |
Exists
Referenceの参照データの存在を検証します。被参照は対象外です。
以下の場合にエラーとなります。
-
指定された
oid
version
に一致するEntityデータが存在しない
Entity型で利用可能です。
Entity型に対応するPropertyタイプは Reference
のみです。
Existsに特化した設定項目はありません。
Packageや独自で作成した複数Entityの一括登録処理の場合は、Entityの登録順番に注意が必要です。 PackageはEntityの順番指定ができないので、分割するかValidationを実行しないことも検討してください。 |
Scripting
GroovyScript書式で検証ロジックを実装します。
以下の場合にエラーとなります。
-
scriptの戻り値が
false
すべての型で利用可能です。
設定項目 | 設定内容 |
---|---|
script |
GroovyScriptを指定します。 戻り値としてBoolean(true:OK、false:NG)を返すように実装する必要があります。 |
bind variable as array type |
多重度が1ではない場合に、value変数に配列をバインドするか、
配列分ループしてvalueにバインドするかを指定します。 |
利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
entity |
対象のEntityデータ。 |
propertyName |
プロパティ名 |
value |
プロパティ値。各Propertyに対応するJava型が格納されています。 |
context |
ValidationContext。
ValidationContextにsetAttributeされた値は、 |
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 Class Name |
PropertyValidatorを実装したクラス名を指定します。 |
bind variable as array type |
多重度が1ではない場合に、value変数に配列をバインドするか、
配列分ループしてvalueにバインドするかを指定します。 |
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を選択します。メタデータのMessageを利用することで、メッセージを共有・管理することができます。 |
Code |
メッセージコードを指定します。この項目は任意です。 バッチ処理やWebサービスなどの独自処理内でコードをレスポンスとして返したい場合などに利用します。 |
Message(Direct) と Message Id が両方指定されている場合は、 Message(Direct) が優先されます。
|
mtp/validation カテゴリに定義されてる標準的なメッセージを利用することも可能です。
|
メッセージ文言として、プロパティ名や値をバインド書式(${xxx}
)で参照することができます
(DirectでもメタデータのMessageでも参照できます)。
利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
name |
プロパティ名 |
entityName |
エンティティ名 |
min |
Length、Range、BinarySizeの |
max |
Length、Range、BinarySizeの |
reference |
Existsの存在しないデータ値。複数ある場合はカンマ区切り |
min、max、referenceについては、他のタイプの場合はバインドされていないため ${min} 、 ${max} 、 ${reference} とそのまま出力されます。
|
上記の他、ValidationContextに setAttribute
された値は、${key}
形式でエラーメッセージに埋め込みが可能となります。
具体的な例は、 Java Class を参照してください。
Validationの操作方法
汎用画面を利用してEntityの更新処理を行う場合は、汎用画面側でValidatorエラーのハンドリングは自動的に行われます。 ここではバッチやWebサービスを利用した独自のEntity更新処理を実装する場合のValidatorエラーハンドリングの方法を説明します。
Entity更新時の操作方法
EntityManagerを利用した insert
、 update
時には
自動的に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チェックを行いたくない場合は、 InsertOption
、 UpdateOption
を利用します。
手動での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型 |
---|---|---|
文字列の前後の空白を除去します。 |
String |
|
改行コードを統一します。 |
String |
|
ICU4JのTransliteratorを利用して変換を行います。 |
String |
|
正規表現を利用して値を置換します。 |
String |
|
Unicode正規化を実施します。 |
String |
|
GroovyScript書式で正規化ロジックを実装します。 |
* |
|
Java Classで正規化ロジックを実装します。 |
* |
Trim White Space
文字列の前後の空白を除去します。
AdminConsole上の編集画面では、Trim White Space
の設定と連動して追加、削除されます。
String型で利用可能です。
Trim White Spaceに特化した設定項目はありません。
Newline Normalizer
改行コードを統一します。
AdminConsole上の編集画面では、Unify Line Breaks Code
の設定と連動して追加、削除されます。
String型で利用可能です。
設定項目 | 設定内容 |
---|---|
Line Breaks Code |
改行コードを指定します |
ICU Transliterator
ICU4JのTransliteratorを利用して変換を行います。
String型で利用可能です。
設定項目 | 設定内容 |
---|---|
Transliterator Id |
ICU4JのTransliteratorのIDを指定します。 |
Regex Replace
正規表現を利用して値を置換します。
String型で利用可能です。
設定項目 | 設定内容 |
---|---|
Regex |
置換対象の正規表現式を指定します。 |
Replacement |
置換後文字列を指定します。 |
Unicode Normalizer
Unicode正規化を実施します。
String型で利用可能です。
設定項目 | 設定内容 |
---|---|
Form |
Unicode正規化形式を指定します。 |
Scripting
GroovyScript書式で正規化ロジックを実装します。
すべての型で利用可能です。
設定項目 | 設定内容 |
---|---|
script |
GroovyScriptを指定します。 戻り値として正規化後の値を返すように実装する必要があります。 |
bind variable as array type |
多重度が1ではない場合に、value変数に配列をバインドするか、
配列分ループしてvalueにバインドするかを指定します。 |
利用可能なバインド変数は以下のものです。
バインド変数 | 設定される値 |
---|---|
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 Class Name |
PropertyNormalizerを実装したクラス名を指定します。 |
bind variable as array type |
多重度が1ではない場合に、value変数に配列をバインドするか、
配列分ループしてvalueにバインドするかを指定します。 |
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を作成します。ただし |
NON_UNIQUE |
一意ではないIndexを作成します。 |
Indexに関する注意点、制約事項を説明します。
-
Property単位でのみ設定が可能です。
複合Index(複数Propertyの結合)はサポートしていません。 -
UNIQUE
、UNIQUE_WITHOUT_NULL
はEntity単位での値の重複をチェックします。
Entity更新時に重複がある場合はエラーとなります。 -
多重度が1以外のPropertyはIndexを指定できません。
-
Expression
Binary
LongText
Refernce
はIndexを指定できません。 -
Entityのバージョン管理を行う場合、
UNIQUE
、UNIQUE_WITHOUT_NULL
として指定したPropertyは変更不可になります。 Entity定義の保存時に自動的にCanEdit = false
として登録されます。 -
既に登録済みのEntityデータが存在する場合にIndex Typeを変更すると、Entity定義の保存時にIndexの再作成処理が実行されます。 大量データが登録されている場合などは考慮が必要です。
UNIQUE
、UNIQUE_WITHOUT_NULL
の場合、一意でないデータが存在すると再作成時にエラーが発生し、定義自体が保存できません。
UNIQUE
、 UNIQUE_WITHOUT_NULL
は、バックエンドでRDBのUnique Indexを利用しています。
MySQLではUnique Indexのbyte制限として767byteまでしか格納することができません。
このため、 UNIQUE
、 UNIQUE_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を変更した場合、自動的にデータの洗い替えは行われない。
プロパティ単位の暗号化を利用する場合、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に格納されます。
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 user 、 mtp については、基盤としての利用を前提にしているため、
アプリで作成するEntityでは利用しないでください。
|
アプリで作成するEntityについては、通常StorageSpaceが未指定のため default
というStorageSpaceに保存されます。
StorageSpaceの機能として、アプリで独自のStorageSpaceを追加することも可能になっています(service-config単位、Tenant単位ではありません)。
独自のStorageSpaceを定義することで
-
一部大量データが格納されるEntityと、その他のEntityをそれぞれ別のStorageSpace(物理テーブル)に格納することができる
-
各StorageSpace単位で物理テーブルの特性を変更することが可能なので、Entityの特性毎にうまく使い分ければ、 RDB上のテーブルスペースが効率的に利用され、RDBのファイルサイズを小さくすることができる
-
StorageSpace毎にパーティション定義内容を変更することができる
-
EntityのPropertyに対して
Store Col Name
を指定することで、 プロパティデータの物理格納カラムを独自で定義したテーブルカラムに直接格納することができる。
これを利用して複合Indexの定義などのRDBネイティブの機能を利用することができる
などのカスタマイズが可能になります。
Entity の StorageSpace が決定するタイミングは、次の3パターンです。
-
Entity 作成時
-
Entity 作成時に、StorageSpace
default
が設定されます。
-
-
Entity の StorageSpace 変更時
-
StorageSpace 設定の変更のみ行われます。
-
運用で利用中でデータが存在する Entity の StorageSpace を変更する場合は、データの移行が必要となります。StorageSpace変更時の注意点を参照ください。
-
-
バッチツール - Storage Space Migration によるデータ移行時
-
ツール実行時に、StorageSpace 設定の変更および、データ移行を行います。
-
次は、このStorageSpace定義を実際に構成するテーブル構造について説明します。
テーブル構造
StorageSpaceはそれぞれで以下のテーブルセットで構成されます。
テーブル名 | 用途 |
---|---|
obj_store |
Entityのデータを格納する汎用テーブル。動的なEntity定義に対応するため予め複数のカラムが定義されている。 |
obj_store_rb |
|
obj_ref |
Entityデータ間の参照情報を格納するテーブル。 |
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名を指定します。 |
tableNamePostfix |
StorageSpace用のテーブルに付加する接尾語を指定します。英数字のみ利用してください。 "obj_store" + __ + Postfix となります。アンダースコア―を2つでつなげます。 |
varcharColumns |
文字列型のプロパティを格納するための列数を指定します。 |
decimalColumns |
Decimal型のプロパティを格納するための列数を指定します。 |
timestampColumns |
Timestamp型のプロパティを格納するための列数を指定します。 |
doubleColumns |
浮動小数点型のプロパティを格納するための列数を指定します。 |
useExternalIndexedTable |
この設定はobj_storeのルールとは直接関係はありません。 |
indexedVarcharColumns |
Index指定された文字列型のプロパティを格納するための列数を指定します。 |
indexedDecimalColumns |
Index指定されたDecimal型のプロパティを格納するための列数を指定します。 |
indexedTimestampColumns |
Index指定されたTimestamp型のプロパティを格納するための列数を指定します。 |
indexedDoubleColumns |
Index指定された浮動小数点型のプロパティを格納するための列数を指定します。 |
useExternalUniqueIndexedTable |
この設定はobj_storeのルールとは直接関係はありません。 |
uniqueIndexedVarcharColumns |
Unique Index指定された文字列型のプロパティを格納するための列数を指定します。 |
uniqueIndexedDecimalColumns |
Unique Index指定されたDecimal型のプロパティを格納するための列数を指定します。 |
uniqueIndexedTimestampColumns |
Unique Index指定されたTimestamp型のプロパティを格納するための列数を指定します。 |
uniqueIndexedDoubleColumns |
Decimal型のプロパティを格納するための列数を指定します。 |
customPartition |
この設定はobj_storeのルールとは直接関係はありません。 obj_store${tableNamePostfix}_テナントID の命名規則に則って、テナント単位でPartitionを作成しているものです。 |
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
による疑似レコード化も抑えることができます。
独自の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_store
、obj_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 を複数テーブルセットで構成することが可能です。
疑似パーティションは以下のような特徴があります。
-
テーブルセットのテーブル名の接尾辞として、最後に
__n
という連番が付与されます。-
0番目のテーブルには連番の接尾辞は付与されません。1番目のテーブルから連番が付与されます。
-
tableNamePostfix が
PS
, tableCount が3
を指定された場合の obj_store テーブルはobj_store__PS
,obj_store__PS__1
,obj_store__PS__2
の3テーブルを利用します。 -
テーブル構造で説明されている全テーブルを、同様のネーミングで定義し作成します。
-
-
疑似パーティションが構成されている StorageSpace に Entity を定義した場合、レコードは決定した疑似パーティション位置へデータが格納されます。
-
レコードを格納するテーブルを
obj_store__PS__1
に決定したら、当該 Entity のレコードは全て同一テーブルに格納されます。(複数の疑似パーティションに跨ることはありません) -
unique, index テーブルに関しても、同様のネーミングルールのテーブルに格納されます。
-
obj_store__PS__1
、obj_unique_str__PS__1
、obj_index_str__PS__1
等
-
-
疑似パーティション位置は 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つのテーブルセットで疑似パーティションが構成されます。 |
設定後に対応するテーブルを作成する必要があります。テーブル定義は バッチツール - Custom Storage Space で作成することができます。
5.5. StorageSpace変更時の注意点
Entity の StorageSpace を変更した場合、登録済のデータは変更後の StorageSpace に移動しません。
もし、登録済みのデータを変更後の StorageSpace へ移行する必要がある場合は、以下のいずれかの方法でデータ移行を行ってください。
AdminConsole のツール 「EntityExplorer」、「Packaging」の Export / Import 機能を利用することで、データを移行します。
以下の手順で作業を実施してください。
-
移行対象データの Export
-
Export データの削除
-
変更前の StorageSpace にデータが残るため、削除を実施します。次のいずれかの方法で削除を実施します。
-
Entity View からデータを削除
-
AdminConsole - EntityExplorer からデータを削除
-
バッチツール - Storage Space Cleaner でデータをクリア(データが大量にある場合に利用を推奨)
-
-
-
Entity の StorageSpace を変更
-
移行対象データの Import
バッチツール - Storage Space Migration を利用することで、StorageSpace の変更および、データ移行を同時に行います。
バッチツール内でメタデータを更新するため、起動中のサーバーはメタデータを再読み込みする必要があります。
6. 全文検索
6.1. 概要
全文検索とは、保存さたEntity内のプロパティの値への横断検索ができる機能です。
ただし、全文検索はリアルタイムでデータが反映されるわけではありません。ご注意ください。 |
iPLAssでは、Lucene、Elasticsearch(OpenSearch) という全文検索エンジンのいずれかを利用することが可能です。
各エンジンの簡単な差は下記を参照してください。
Lucene | Elasticsearch(OpenSearch) | |
---|---|---|
概要 |
Javaベースのオープンソースの全文検索ライブラリ。 |
Elasticsearch(OpenSearch)はLuceneをベースに開発されたオープンソースの全文検索エンジン。 |
データ保存先 |
APサーバのローカルストレージ |
Elasticsearch(OpenSearch)サーバ内 |
Analyzer(※)の扱いやすさ |
デフォルトで使えるAnalyzerを適用する場合は、とても簡単。(複数種類有) |
デフォルトで使える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 を利用する場合で設定内容が異なります。
Lucene設定
全文検索に関する設定をFulltextSearchServiceに設定します。 Indexファイルの保存場所、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。
次に設定ファイルの設定例を示します。
デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。
<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ファイルを格納するルートディレクトリを指定します |
主要な設定項目を設定した例を以下に示します。
<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 |
全文検索機能を有効にする場合は |
||
directory |
indexファイルを保存するルートディレクトリを指定します。 このディレクトリ配下にテナント、Entity定義毎にindexファイルが作成されます。 |
||
maxRows |
全文検索サーバから取得する検索結果の最大件数を設定します。
|
||
throwExceptionWhenOverLimit |
false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。 下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。 true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。 |
||
binaryParser |
BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。 |
||
analyzerSetting |
利用するAnalyzerの設定を行います。
classには SimpleAnalyzerSettingの場合、Analyzerのクラス名(className)を指定可能です。 JapaneseAnalyzerSettingの場合、加えてmode、userDictionaryなどの指定が可能です。 また、
Entity定義単位に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
中国語分割(簡体字中国語または中国語と英語が混在している文字列に有効)
※ Gradle 依存関係にorg.apache.lucene:lucene-analysis-smartcn
の追加が必要です。 -
org.apache.lucene.analysis.ja.JapaneseAnalyzer
日本語分割(Searchモード):形態素解析しつつ、複合語で構成された単語を適切に分割します。
Elasticsearch設定
全文検索に関する設定をFulltextSearchServiceに設定します。 サーバURL、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。
次に設定ファイルの設定例を示します。
デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。
<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を指定します |
主要な設定項目を設定した例を以下に示します。
<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 |
全文検索機能を有効にする場合は |
||
elasticsearchUrl |
ElasticsearchのサーバURLを指定します。 |
||
maxRows |
全文検索サーバから取得する検索結果の最大件数を設定します。
|
||
throwExceptionWhenOverLimit |
false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。 下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。 true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。 |
||
binaryParser |
BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。 |
||
analysisFactory |
カスタムでAnalyzer等を定義したい場合に利用します。
classには |
||
defaultAnalyzerProperty |
デフォルトで利用するAnalyzer名を指定します。 classには |
||
analyzerPropertyPerEntity |
Entity定義単位でAnalyzerを切り替えたい場合、Entity名とAnalyzerPropertyをMap形式で指定します。 |
(非推奨)OpenSearch設定
全文検索に関する設定をFulltextSearchServiceに設定します。 サーバURL、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。
AWS SDK for Java 1.x はメンテナンスモードになっており、2025年12月 にサポートを終了する予定です。 |
次に設定ファイルの設定例を示します。
デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。
<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を指定します |
主要な設定項目を設定した例を以下に示します。
<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 |
全文検索機能を有効にする場合は |
||
openSearchUrl |
OpenSearchのサーバURLを指定します。 |
||
httpRequestInterceptorFactory |
httpRequestInterceptorを生成するFactoryクラスを設定します。
BASIC認証ではなく、IAM認証情報を使用してリクエストを署名したい場合、実装クラスである |
||
maxRows |
全文検索サーバから取得する検索結果の最大件数を設定します。
|
||
throwExceptionWhenOverLimit |
false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。 下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。 true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。 |
||
binaryParser |
BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。 |
||
analysisFactory |
カスタムでAnalyzer等を定義したい場合に利用します。
classには |
||
defaultAnalyzerProperty |
デフォルトで利用するAnalyzer名を指定します。 classには |
||
analyzerPropertyPerEntity |
Entity定義単位でAnalyzerを切り替えたい場合、Entity名とAnalyzerPropertyをMap形式で指定します。 |
OpenSearch設定
全文検索に関する設定をFulltextSearchServiceに設定します。 サーバURL、Analyzerなどに関する設定などを行います。 詳細は FulltextSearchService を参照してください。
次に設定ファイルの設定例を示します。
デフォルト値を利用し、必要最低限の設定のみを行った設定例を以下に示します。
<service>
<interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>
<class>org.iplass.mtp.impl.fulltextsearch.opensearch.OpenSearchFulltextSearchService</class> (1)
<property name="useFulltextSearch" value="true" /> (2)
<property name="restClientFactory" class="org.iplass.mtp.impl.fulltextsearch.opensearch.DefaultRestClientFactory">
<property name="openSearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/> (3)
</property>
</service>
1 | 実装クラスとしてOpenSearchFulltextSearchServiceを指定します |
2 | 全文検索機能を有効化する場合trueを指定します |
3 | OpenSearchのサーバURLを指定します |
主要な設定項目を設定した例を以下に示します。
<service>
<interface>org.iplass.mtp.impl.fulltextsearch.FulltextSearchService</interface>
<class>org.iplass.mtp.impl.fulltextsearch.opensearch.OpenSearchFulltextSearchService</class>
<property name="useFulltextSearch" value="true" />
<!--
<property name="restClientFactory" class="org.iplass.mtp.impl.fulltextsearch.opensearch.DefaultRestClientFactory">
<property name="openSearchUrl" value="{SCHEME}://{ADDRESS}:{PORT}"/>
</property>
-->
<property name="transportFactory" class="org.iplass.mtp.impl.fulltextsearch.openserarch.awsv2.AwsSdk2OpenSearchTransportFactory">
<property name="host" value="{ADDRESS}:{PORT}" />
<!-- es:マネージド型クラスター、 aoss:サーバーレス -->
<property name="serviceName" value="es" />
<property name="region" value="ap-northeast-1" />
</property>
<property name="maxRows" value="1000" />
<property name="throwExceptionWhenOverLimit" value="true"/>
<property name="analysisFactory" class="org.iplass.mtp.impl.fulltextsearch.opensearch.analysis.DefaultAnalysisFactory">
<property name="analyzer" >
<property name="my_kuromoji" class="org.iplass.mtp.impl.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.fulltextsearch.opensearch.mappings.AnalyzerProperty">
<property name="analyzer" value="my_kuromoji"/>
</property>
</property>
</service>
各設定項目の概要を以下に説明します。
プロパティ名 | 内容説明 | ||
---|---|---|---|
useFulltextSearch |
全文検索機能を有効にする場合は |
||
restClientFactory |
OpenSearchのサーバURLを指定します。BASIC認証を利用する場合は本設定を利用します。 |
||
transportFactory |
OpenSearchのサーバURLを指定します。IAM認証情報を使用してリクエストを署名します。AWSSetting の設定が必要となります。 |
||
maxRows |
全文検索サーバから取得する検索結果の最大件数を設定します。
|
||
throwExceptionWhenOverLimit |
false:maxRowsの設定値以上に検索結果件数が取得できた場合でも、maxRowsの設定値分の件数は結果を表示します。 下記の画面は設定値以上に取得出来た場合となります。設定値未満の場合、メッセージ表示はありません。 true:maxRowsの設定値以上に検索結果件数が取得できた場合、結果を表示せずに条件を絞り込むようメッセージで催促されます。 |
||
binaryParser |
BinaryReference解析用のParserを設定します。 Apache Tikaを利用して、特定のバイナリ内もインデックスすることができます。 |
||
analysisFactory |
カスタムでAnalyzer等を定義したい場合に利用します。
classには |
||
defaultAnalyzerProperty |
デフォルトで利用するAnalyzer名を指定します。 classには |
||
analyzerPropertyPerEntity |
Entity定義単位でAnalyzerを切り替えたい場合、Entity名とAnalyzerPropertyをMap形式で指定します。 |
6.3. 利用方法
Indexの設定
AdminConsoleからIndex対象とするEntity、および、Entityの列の設定をします。
全文検索対象としたいEntityを開き、「crawl for full text search」にチェックしてください。
すると、デフォルトでIndex対象となりうるプロパティの「Crawl」列にチェックが出ます。
各プロジェクトで必要なプロパティに対してのみチェックがあることを確認し、保存してください。
typeがBinaryであるプロパティクを全文検索対象とした場合、バイナリのファイル名 + " " + バイナリのファイルタイプ という値で登録されます。
|
Indexの作成
全文検索で検索が行われるデータは下記のIndex作成をした時点でのデータとなります。(ただし取得(表示)されるデータは、検索時点の最新データとなります)
そのため、新しく登録したデータをIndexに含めたいなどの場合は、必ずIndexの再作成を実施してください。
-
AdminConsoleから
AdminConsole画面の左下メニューにあるToolsのEntityExplorerを選択します。
全文検索を利用する設定になっている場合、「Entity Crawl」タブが表示されます。
「Entity Crawl」タブのリストには「crawl for full text search」にチェックをつけたEntityのみが表示されます。クローリングには選択したEntityのみを対象に実施する方法と、全Entityを全てクローリングする2種類があります。
A. 任意のEntityのみを対象としてクローリングしたい場合はリストのEntityにチェックをいれ、
Start Crawl
ボタンをクリックして下さい。B. クローリング対象Entityを全てクローリングしたい場合は
Re Crawl All Entity
ボタンをクリックして下さい。この場合、チェックをいれていないEntityも全てが対象となります。C. クローリング処理が完了しましたら、INDEXデータの変更を反映させるために、
Refresh
ボタンをクリックしてください。 -
バッチから
iPLAss SDKで配布しているcrawl_entity.bat(sh)
をクーロン等にセットすることで、バッチ起動が可能です。
バッチの詳細についてはEntity Crawlを参照してください。
検索機能
全文検索機能を有効にしている場合のみ画面上部に拡大鏡マークが表示されます。 拡大鏡マークをクリックすると、検索プルダウンが表示されます。 また、このプルダウンに表示されるエンティティはAdminConsoleでIndex対象としたEntityのみとなります。 プルダウン右にあるテキストボックスに文字列を入力して検索することで全文検索が実行されます。 エンティティを選択しない場合はIndex対象とした全Entityが対象なり、下記のような検索結果画面となります。
全文検索機能でのソートは以下のようになっています。
第1ソート:スコア(降順)
第2ソート:Entity定義名(昇順)
スコアとは、検索文字列と検索対象値(行単位)の関連度が数値化されたものとなります。 これらはLucene内部で算出された値を利用しています。 簡単に条件を表すと、以下に一致すればするほどスコア値が高くなる傾向があります。
-
検索文字列の単語がより多く含まれている
-
検索対象の値が短い
-
全検索対象の中で希少単語が含まれている
実行環境として、全文検索の取得上限(maxRows設定)を 5
に設定し、
java
という文字列が3つ出てくる情報を4つ、2つ出てくる情報(緑枠の部分)を3つ用意している状態です。
(全文検索対象のプロパティは「検索対象1」~「検索対象3」)
スコア値が高くなる傾向の1つである「検索文字列の単語がより多く含まれている」が適用されたことにより、
java
という文字列が2つ出てくる情報は1件分しか表示できません。
java
という文字列が2つ出てくる情報の種類として、1件はプロパティに設定した値が java
だけのもののみ、
その他2件は java
の他に文字列を含んでいる値になっています。
「検索対象の値が短い」という条件が適用されたことにより、 java
だけ登録した値がスコアとして高くなり、
全文検索結果として表示されています。
ロジックから検索する方法は2種類あります。
-
全エンティティを対象に検索する場合
EntityManagerのfulltextSearchEntityを利用して下さい。複数のEntityに対して横断的に一括で検索します。 ただし、取得できるデータはEntity毎にマージされたものとなります。 -
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をAdminConsoleから設定することが可能です。
まず、対象のEntity毎に全文検索結果に表示したい項目などを設定したViewをSearch Layoutで作成してください。
その後、AdminConsole画面のMetaDataSettings内にある View Components > TopView
の設定を変更します。
TopViewの機能概要、作成方法についてはTopViewの章を参照してください。
右にあるメニューから、 Toolbar Parts > Fulltext Search(PU)
を選択し、Main Area(Droppable P(Parts))にドラッグ&ドロップしてください。
ドラッグ&ドロップして出てきたFulltext Searchの設定ボタンをクリックすると、 crawl for full text search
にチェックをつけたEntityのみが表示されます。
Entity View列に設定したSearchViewを使用して、全文検索結果となったEntityの情報を表示します。
別途対象EntityのSearch ViewでカスタマイズしたViewを作成することで、Entity Viewの選択リストに表示されるようになります。 |
その他の設定可能な項目は以下になります。
設定項目 | 設定内容 |
---|---|
Display search textbox |
本項目にチェックを入れると、ヘッダーに全文検索用のテキストボックスが表示されます。 |
Display user name in privileged execution |
本項目にチェックを入れると、UserPropertyEditorが設定されているプロパティに対し、ユーザー情報のEntity、またはユーザー名のプロパティに参照権限が無いユーザーでも、特権実行をしてユーザー名を表示することができます。 |
Entity View |
全文検索の結果表示で利用するViewを選択します。 |
show in search list |
本項目にチェックを入れると、全文検索実行時の対象として、個別に選択が可能になります。 |
全文検索結果を表示するSearchViewのSearchFormView Settingに自作したアクションを設定することで、 カスタマイズした画面への遷移が可能となります。
-
詳細リンク先アクション
-
編集リンク先アクション
遷移先で取得可能なリクエスト情報は以下です。
パラメータ名 | 内容説明 |
---|---|
defName |
選択した情報のEntity定義名 |
oid |
選択した情報のOID |
version |
選択した情報のVersion |