null Liferayテーブルを見てみよう〜Webコンテンツ編

こんにちはナクラです。

今回はWebコンテンツについて見ていきましょう。

LiferayではWebコンテンツに対して、データベースのテーブル名称としては「JournalArticle」が使われています。
パッとはわかりづらいのですが、昔から使われているものなので今後変わることもあまり期待できそうにないですね。
テーブル名と同様バックエンドサービスの名称もJournalArticleLocalServiceになっていますので、そこも注意点です。

さて、このJournalArticleテーブルを見ていく前に、Webコンテンツに関連する他のテーブルについても少し抑えておきましょう。

LiferayではWebコンテンツを構成するためには、
以下のものが必要です。
・Webコンテンツのデータを構造を決めるストラクチャ
・Webコンテンツのストラクチャの表示内容を定めるテンプレート
・Webコンテンツ自体のデータ

このうちWebコンテンツ自体のデータがJournalArticleで、
ストラクチャはDDMStructure、テンプレートはDDMTemplateにデータが登録されます。
DDMStructureとDDMTemplateについては、Webコンテンツだけのものではなく、
他のエンティティのデータも含まれています。

これらの関係を図に表すと以下のようになっています。

 

DDMStructureのテーブル定義は以下のようになっています。

mysql> desc DDMStructure;
+-------------------+-------------+------+-----+---------+-------+
| Field             | Type        | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+---------+-------+
| mvccVersion       | bigint(20)  | NO   |     | 0       |       |
| uuid_             | varchar(75) | YES  | MUL | NULL    |       |
| structureId       | bigint(20)  | NO   | PRI | NULL    |       |
| groupId           | bigint(20)  | YES  | MUL | NULL    |       |
| companyId         | bigint(20)  | YES  | MUL | NULL    |       |
| userId            | bigint(20)  | YES  |     | NULL    |       |
| userName          | varchar(75) | YES  |     | NULL    |       |
| versionUserId     | bigint(20)  | YES  |     | NULL    |       |
| versionUserName   | varchar(75) | YES  |     | NULL    |       |
| createDate        | datetime(6) | YES  |     | NULL    |       |
| modifiedDate      | datetime(6) | YES  |     | NULL    |       |
| parentStructureId | bigint(20)  | YES  | MUL | NULL    |       |
| classNameId       | bigint(20)  | YES  | MUL | NULL    |       |
| structureKey      | varchar(75) | YES  | MUL | NULL    |       |
| version           | varchar(75) | YES  |     | NULL    |       |
| name              | longtext    | YES  |     | NULL    |       |
| description       | longtext    | YES  |     | NULL    |       |
| definition        | longtext    | YES  |     | NULL    |       |
| storageType       | varchar(75) | YES  |     | NULL    |       |
| type_             | int(11)     | YES  |     | NULL    |       |
| lastPublishDate   | datetime(6) | YES  |     | NULL    |       |
+-------------------+-------------+------+-----+---------+-------+

この中のclassNameIdというカラムには、DDMStructureが対応しているエンティティのクラスのIDが表示されます。
試しに、classIdを登録しているclassName_テーブルとDDMStructureをジョインして確認してみると、以下のようになります。

mysql> select A.structureId,A.structurekey,A.classNameId,B.value from DDMStructure A inner join className_ B on A.classNameId = B.classNameId;
+-------------+-------------------+-------------+---------------------------------------------------------------+
| structureId | structurekey      | classNameId | value                                                        
+-------------+-------------------+-------------+---------------------------------------------------------------+
|       34402 | BASIC-WEB-CONTENT |       20501 | com.liferay.journal.model.JournalArticle                      |
|       34216 | CONTACTS          |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34220 | EVENTS            |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34224 | INVENTORY         |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34228 | ISSUES TRACKING   |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34232 | MEETING MINUTES   |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34236 | TO DO             |       29203 | com.liferay.dynamic.data.lists.model.DDLRecordSet             |
|       34420 | CONTACTS          |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34424 | EVENTS            |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34428 | INVENTORY         |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34432 | ISSUES TRACKING   |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34436 | MEETING MINUTES   |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34440 | TO DO             |       34272 | com.liferay.portal.workflow.kaleo.forms.model.KaleoProcess    |
|       34326 | TIKARAWMETADATA   |       34325 | com.liferay.document.library.kernel.util.RawMetadataProcessor |
+-------------+-------------------+-------------+---------------------------------------------------------------+

ここで、classNameIdが20501となっているものがWebコンテンツを示すクラスIDです。
今、BASIC-WEB-CONTENTというDDMStructureがWebコンテンツ用のDDMStructureであることがわかります。
デフォルトではLiferayのWebコンテンツのタイプ(ストラクチャ)としては
「BASIC-WEB-CONTENT(基本のWebコンテンツ)」のみが用意されています。

また、DDMTemplateはDDMStructureと紐づいています。
1つのDDMStructureに大して、複数のDDMTemplateを紐付けることができます。

DDMTempalteのテーブル定義は以下のようになっています。

mysql> desc DDMTemplate;
+---------------------+-------------+------+-----+---------+-------+
| Field               | Type        | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+-------+
| mvccVersion         | bigint(20)  | NO   |     | 0       |       |
| uuid_               | varchar(75) | YES  | MUL | NULL    |       |
| templateId          | bigint(20)  | NO   | PRI | NULL    |       |
| groupId             | bigint(20)  | YES  | MUL | NULL    |       |
| companyId           | bigint(20)  | YES  |     | NULL    |       |
| userId              | bigint(20)  | YES  |     | NULL    |       |
| userName            | varchar(75) | YES  |     | NULL    |       |
| versionUserId       | bigint(20)  | YES  |     | NULL    |       |
| versionUserName     | varchar(75) | YES  |     | NULL    |       |
| createDate          | datetime(6) | YES  |     | NULL    |       |
| modifiedDate        | datetime(6) | YES  |     | NULL    |       |
| classNameId         | bigint(20)  | YES  | MUL | NULL    |       |
| classPK             | bigint(20)  | YES  | MUL | NULL    |       |
| resourceClassNameId | bigint(20)  | YES  |     | NULL    |       |
| templateKey         | varchar(75) | YES  | MUL | NULL    |       |
| version             | varchar(75) | YES  |     | NULL    |       |
| name                | longtext    | YES  |     | NULL    |       |
| description         | longtext    | YES  |     | NULL    |       |
| type_               | varchar(75) | YES  | MUL | NULL    |       |
| mode_               | varchar(75) | YES  |     | NULL    |       |
| language            | varchar(75) | YES  | MUL | NULL    |       |
| script              | longtext    | YES  |     | NULL    |       |
| cacheable           | tinyint(4)  | YES  |     | NULL    |       |
| smallImage          | tinyint(4)  | YES  |     | NULL    |       |
| smallImageId        | bigint(20)  | YES  | MUL | NULL    |       |
| smallImageURL       | longtext    | YES  |     | NULL    |       |
| lastPublishDate     | datetime(6) | YES  |     | NULL    |       |
+---------------------+-------------+------+-----+---------+-------+

DDMTemplateのデータを一部抽出してみてみましょう。

mysql> select templateKey,classNameId,classPK from DDMTemplate where companyId =20101;
+-----------------------------------------------------+-------------+---------+
| templateKey                                         | classNameId | classPK |
+-----------------------------------------------------+-------------+---------+
| BREADCRUMB-ARROWS-FTL                               |       34042 |       0 |
| BREADCRUMB-HORIZONTAL-FTL                           |       34042 |       0 |
| BREADCRUMB-VERTICAL-FTL                             |       34042 |       0 |
| WIKI-SOCIAL-FTL                                     |       22103 |       0 |
| RSS-NAVIGATION-FTL                                  |       34060 |       0 |
| LIST-MENU-FTL                                       |       20135 |       0 |
| NAV-PILLS-FTL                                       |       20135 |       0 |
| NAV-PILLS-JUSTIFIED-FTL                             |       20135 |       0 |
| NAV-PILLS-STACKED-FTL                               |       20135 |       0 |
| NAV-TABS-FTL                                        |       20135 |       0 |
| NAV-TABS-JUSTIFIED-FTL                              |       20135 |       0 |
| NAVBAR-BLANK-FTL                                    |       20135 |       0 |
| NAVBAR-BLANK-JUSTIFIED-FTL                          |       20135 |       0 |
| NAVBAR-DEFAULT-FTL                                  |       20135 |       0 |
| NAVIGATION-MACRO-FTL                                |       20135 |       0 |
| SPLIT-BUTTON-DROPDOWNS-FTL                          |       20135 |       0 |
| ASSET-CATEGORIES-NAVIGATION-MULTI-COLUMN-LAYOUT-FTL |       20013 |       0 |
| DOCUMENTLIBRARY-CAROUSEL-FTL                        |       34103 |       0 |
| SITE-MAP-MULTI-COLUMN-LAYOUT-FTL                    |       20044 |       0 |
| ASSET-TAGS-NAVIGATION-COLOR-BY-POPULARITY-FTL       |       20017 |       0 |
| LANGUAGE-ICON-FTL                                   |       34113 |       0 |
| LANGUAGE-ICON-MENU-FTL                              |       34113 |       0 |
| LANGUAGE-LONG-TEXT-FTL                              |       34113 |       0 |
| LANGUAGE-SELECT-BOX-FTL                             |       34113 |       0 |
| LANGUAGE-SHORT-TEXT-FTL                             |       34113 |       0 |
| BLOGS-BASIC-FTL                                     |       34129 |       0 |
| BLOGS-CARD-FTL                                      |       34129 |       0 |
| ASSET-PUBLISHER-GEOLOCALIZED                        |       20015 |       0 |
| ASSET-PUBLISHER-RICH-SUMMARY-FTL                    |       20015 |       0 |
| BASIC-WEB-CONTENT                                   |       33999 |   34402 |
+-----------------------------------------------------+-------------+---------+

WEBコンテンツのテンプレートはtemplateKeyがBASIC-WEB-CONTENTになっているものですが、
classPKの値が、BASIC-WEB-CONTENTのDDMStructureのStructureIdと同じ値(34402)になっているのが気が付いたでしょうか。
このclassPKの値によって、DDMStructureとDDMTemplateの紐付けが行われています。

ここまでで、Webコンテンツを構成するストラクチャとテンプレートのデータが確認できたので、
実際のWebコンテンツデータであるJournalArticleテーブルを見ていきましょう。

JournalArticleテーブルの定義は以下のようになっています。

mysql> desc JournalArticle;
+-------------------+--------------+------+-----+---------+-------+
| Field             | Type         | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| mvccVersion       | bigint(20)   | NO   |     | 0       |       |
| uuid_             | varchar(75)  | YES  | MUL | NULL    |       |
| id_               | bigint(20)   | NO   | PRI | NULL    |       |
| resourcePrimKey   | bigint(20)   | YES  | MUL | NULL    |       |
| groupId           | bigint(20)   | YES  | MUL | NULL    |       |
| companyId         | bigint(20)   | YES  | MUL | NULL    |       |
| userId            | bigint(20)   | YES  |     | NULL    |       |
| userName          | varchar(75)  | YES  |     | NULL    |       |
| createDate        | datetime(6)  | YES  |     | NULL    |       |
| modifiedDate      | datetime(6)  | YES  |     | NULL    |       |
| folderId          | bigint(20)   | YES  |     | NULL    |       |
| classNameId       | bigint(20)   | YES  | MUL | NULL    |       |
| classPK           | bigint(20)   | YES  |     | NULL    |       |
| treePath          | longtext     | YES  |     | NULL    |       |
| articleId         | varchar(75)  | YES  |     | NULL    |       |
| version           | double       | YES  |     | NULL    |       |
| urlTitle          | varchar(255) | YES  |     | NULL    |       |
| content           | longtext     | YES  |     | NULL    |       |
| DDMStructureKey   | varchar(75)  | YES  | MUL | NULL    |       |
| DDMTemplateKey    | varchar(75)  | YES  | MUL | NULL    |       |
| defaultLanguageId | varchar(75)  | YES  |     | NULL    |       |
| layoutUuid        | varchar(75)  | YES  | MUL | NULL    |       |
| displayDate       | datetime(6)  | YES  | MUL | NULL    |       |
| expirationDate    | datetime(6)  | YES  |     | NULL    |       |
| reviewDate        | datetime(6)  | YES  |     | NULL    |       |
| indexable         | tinyint(4)   | YES  |     | NULL    |       |
| smallImage        | tinyint(4)   | YES  |     | NULL    |       |
| smallImageId      | bigint(20)   | YES  | MUL | NULL    |       |
| smallImageURL     | longtext     | YES  |     | NULL    |       |
| lastPublishDate   | datetime(6)  | YES  |     | NULL    |       |
| status            | int(11)      | YES  |     | NULL    |       |
| statusByUserId    | bigint(20)   | YES  |     | NULL    |       |
| statusByUserName  | varchar(75)  | YES  |     | NULL    |       |
| statusDate        | datetime(6)  | YES  |     | NULL    |       |
+-------------------+--------------+------+-----+---------+-------+

いくつかの項目について確認していきましょう。

●id_カラム、resourcePrimKeyカラム、articleIdカラム、versionカラム
Webコンテンツが作成される際に、まずWebコンテンツのリソースとして、リソースキーと記事IDが発行されます。
このデータはJournalArticleResourceテーブルで管理されます。
JournalArticleResourceテーブルの定義は以下のようになっています。

mysql> desc JournalArticleResource;
+-----------------+-------------+------+-----+---------+-------+
| Field           | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| mvccVersion     | bigint(20)  | NO   |     | 0       |       |
| uuid_           | varchar(75) | YES  | MUL | NULL    |       |
| resourcePrimKey | bigint(20)  | NO   | PRI | NULL    |       |
| groupId         | bigint(20)  | YES  | MUL | NULL    |       |
| companyId       | bigint(20)  | YES  |     | NULL    |       |
| articleId       | varchar(75) | YES  |     | NULL    |       |
+-----------------+-------------+------+-----+---------+-------+

Webコンテンツの実体であるJournalArticleのレコードの登録時に、
プライマリキーであるid_が払い出され、リソースとの外部キーとして、JournalArticlresourceのresourcePrimKeyとarticleIdが使われます。
Webコンテンツを更新すると、元のレコードはそのままで、
新しいid_のレコードがバージョン違いのWebコンテンツとして作成されます。
Webコンテンツ作成時のバージョンについてはversionカラムに設定されて、初期値は1.0で、0.1刻みで更新されていきます。
新しいレコードではresourcePrimKeyカラム、articleIdカラムは元のレコードと同じです。
なので、JournalArticleのレコードで、resourcePrimKeyまたはarticleIdが同じレコード達を抽出すれば、
バージョン管理されたWebコンテンツを取り出すことができます。

● classNameIdカラムとclassPKカラム
これらのカラムについては通常のWebコンテンツの場合は0の値が入ります。
どういった場合に値が入るのでしょうか。
実は、Webコンテンツのストラクチャを作成した場合、そのストラクチャに対してデフォルト値を設定することができます。
このときに設定したデフォルト値の情報は特別なWebコンテンツとしてJouranalArticleテーブルに登録されます。
どのストラクチャについてのデフォルト値のデータであるかを示すために、
classNameIdにはストラクチャを表すクラスのIDが、classPKにはデフォルト値を設定したストラクチャのstructureIdが設定されることになっています。

●folderIdカラム
このカラムにはWebコンテンツを格納しているフォルダのIDが設定されます。
このフォルダについてはDocument管理のフォルダであるDLFolderではなく、JournalFolderで管理されています。
サイトのルートフォルダに格納している場合は0が入ります。

●contentカラム
このカラムにはコンテンツのデータが含まれます。
データはXML形式で登録されています。
複数言語のコンテンツを登録した、以下のような感じで、複数言語分のコンテンツのデータが含まれます。

<root available-locales="ja_JP,en_US" default-locale="en_US">
    <dynamic-element name="content" type="text_area" index-type="text" instance-id="nzvw">
        <dynamic-content language-id="ja_JP"><![CDATA[<p>サンプルコンテンツ</p>]]></dynamic-content>
        <dynamic-content language-id="en_US"><![CDATA[<p>Sample &nbsp;content</p>]]></dynamic-content>
    </dynamic-element>
</root>     

このデータを見ると、Webコンテンツの登録の際にタイトルや概要のデータが含まれていないことに気づきます。
実は、タイトルと概要については、JournalArticleLocalizationテーブルで管理されています。
JournalArticleLocalizationテーブルの定義は以下のようになっています。

mysql> desc JournalArticleLocalization;
+-----------------------+--------------+------+-----+---------+-------+
| Field                 | Type         | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+-------+
| mvccVersion           | bigint(20)   | NO   |     | 0       |       |
| articleLocalizationId | bigint(20)   | NO   | PRI | NULL    |       |
| companyId             | bigint(20)   | YES  |     | NULL    |       |
| articlePK             | bigint(20)   | YES  | MUL | NULL    |       |
| title                 | varchar(400) | YES  |     | NULL    |       |
| description           | longtext     | YES  |     | NULL    |       |
| languageId            | varchar(75)  | YES  |     | NULL    |       |
+-----------------------+--------------+------+-----+---------+-------+

この中のarticlePKの値が、JournalArticleのid_フィールドと紐づくようになっています。
languageIdのカラムがあることからわかるように、複数言語に対応したコンテンツの場合は、登録した各言語ごとに1レコードが作成されます。

●statusカラム
このカラムにはWebコンテンツの状態を表すデータが設定されます。
設定値についてはcom.liferay.portal.kernel.workflow.WorkflowConstants
で定義されたstatus用の値が入ります。
公開中:0
公開申請中:1
下書き保存:2
公開終了:3
公開前:7
などのようになっています。

以上で、Webコンテンツに関連するJournalArticleテーブルについての概要を見てきました。

Webコンテンツについては、他にカテゴリやタグ、関連するコンテンツなどのメタデータを登録することができますが、
それらについては、LiferayのAssetフレームワークの中でいろいろな種類のエンティティと統一的に管理されているため、改めて紹介できればと思います。

RANKING
2021.1.08
2020.12.28
2020.12.01
2020.10.30
2020.12.18