WordPress 徹底解析(WordPressを拡張するプログラムの構成法 – 処理のクラス化)

「WordPress 徹底解析(WordPressを拡張するプログラムの構成法 – 処理のクラス化)」いきます。 🙂

前回は、アクションフックの動きと簡単な処理の実装まで行ってみました。

実はこの記事、”プラグインをつくる”としてしまったのですが、WordPress のフックの機能はテーマの functions.php でも同様に使える手法です。

テンプレートファイルの functions.php は、プラグインファイルと読み込み順番が若干違うだけでプラグインと同様な実装ができます。テーマと同時に有効になるプラグインファイルと考えても差し支えないでしょう。というわけで、テーマを主につくる方も読み進めていただければと思います。紹介しているソースも functions.php にかけばそのまま動くはずです。

さて、今回は以下のような WordPress を拡張する上でのプログラム構成のノウハウを、引き続きアクションフックのプラグインのソースを元に紹介していきます。

  1. 処理のクラス化
  2. 外部 API の呼び出し
  3. テンプレートファイルに情報を出力する方法
  4. 外部 API 呼び出しの並列化
  5. 管理画面をつくる

まずは「1. 処理のクラス化」より。


処理のクラス化

前回紹介した、アクションフックを使う基本コードは以下のようなものでした。

function prepare($post_ID, $post) {
    die("test");
}

add_action('publish_post', 'prepare', 10, 2);

これをベースに以下の処理を実装していきます。

  • 「記事の公開時」にその日のお天気を LWWS API に問い合わせカスタムフィールドに格納する。
  • 格納されたお天気情報をテンプレートファイルの記述でアイコン出力する。

大きく2つの機能があり、双方ともカスタムフィールドの値の処理(設定と取得)で関連しています。これらの処理には関数が2個以上は必要そうです。

プラグインやテンプレートファイルの functions.php に定義する関数や変数はグローバルスコープになります。WordPress 本体や他のプラグインと共通的な空間に定義されますので、複数が大きくなり関数が増えるとお互いの干渉が気になってきます。大きなところでは、変数や関数名称の重複です。

このような場合、PHP のクラスの機能を名前空間として使い処理をまとめると、グローバルに対する干渉を最小限に抑えることが出来ます。(またオブジェクト指向をつかったトリックも使えるようになります)

先のグローバル関数をひとつ使ったアクションフックの定義をクラスを使ったものに変更すると次のようになります。

class Otenki {
    function prepare($post_ID, $post) {
        die("test");
    }
}

$otenki = new Otenki();
add_action('publish_post', array($otenki, 'prepare'), 10, 2);

クラスを定義(class Otenki {})し、その下で $otenki 変数に Otenki オブジェクトのインスタンス内を格納します。

$otenki = new Otenki();

クラス内に移動したメソッド(function prepare() { } )を add_action するには、’prepare’ と関数名のみを指定していた引数を、 array($otenki, ‘prepare’) と変更しインスタンスを特定できるようにします。

add_action('publish_post', /*ここ→*/array($otenki, 'prepare'), 10, 2);

以上の変更でクラス Otenki が名前空間代わりになります。クラス内部に実装するメソッドや定数・変数は、他との名前の重複など考えず自由に定義できます。

なお、クラス名 Otenki とそのインスタンスを格納する $otenki 変数は依然としてグローバルです。この部分だけ他との干渉を意識します。

(WordPress とのインターフェースになるクラスはいろいろな機能が実装されてしまうためクラス名には悩みますが、、SI業界的(?)には OtenkiPluginFaçade とかでしょうか。モジュール分割の規模によって決めると良いと思います。今回は処理が小さくひとつのクラスで済みそうなので単純に Otenki としました)

では「お天気情報の取得」と「テンプレートファイルからお天気情報を出力する」2つのメソッドを実装します。 まずはソースの骨組みのみ。

class Otenki {

    /**
     * カスタムフィールド・メタキー.
     */
    const META_KEY = 'otenki';

    /**
     * APIバージョン情報(V1/JSON).
     */
    const LWWS_V1_JSON = 'LWWS_V1_JSON';

    /**
     * 記事公開フックで天気情報を取得をする.
     *
     * @param $post_ID
     * @param $post
     * @return none
     */
    function prepare($post_ID, $post) {
        // お天気 API を呼び出し
        // Otenki::META_KEY, Otenki::LWWS_V1_JSON を用いて
        // カスタムフィールドに登録
    }

   /**
    * カスタムフィールドに取得したお天気アイコンを出力.
    *
    * @param none
    * @return none
    */
    function output() {
        // Otenki::META_KEY, Otenki::LWWS_V1_JSON を用いて
        // カスタムフィールドを取得しアイコン HTML を出力
    }
}

$otenki = new Otenki();
add_action('publish_post', array($otenki, 'prepare'), 10, 2);

class 内に prepare と output メソッドが実装され、共通するカスタムフィールドのキーなどが const(定数)で定義されていることが分かります。処理の class 化を行うと、このような共通項がグローバルへの影響無しに自由に実装できるようになります。

さて、アクションフックにより「お天気情報の取得」を担う prepare メソッドの呼び出しはうまくいきそうですが、テンプレートファイルにお天気情報を出力する output メソッドはどのように呼び出せばいいかという疑問がわいてきます。

これは、Otenki クラスのインスタンスが格納されている $otenki 変数がグローバルスコープであることを利用して、テーマのテンプレートファイル内で次のように呼び出すことができます。

$otenki->output();

ただ WordPress のテンプレートタグ的には、オブジェクト指向のメタファーが入ってしまうため、若干違和感があります。WordPress 本体では似たケースで次のような実装がされています。

テンプレートのループで使われる the_post() 関数。

wp-includes/query.php

/**
 * Iterate the post index in the loop.
 *
 * @see WP_Query::the_post()
 * @since 1.5.0
 * @uses $wp_query
 */
function the_post() {
    global $wp_query;

    $wp_query->the_post();
}

グローバルスコープののインスタンスが格納されている変数を関数に持ってきてメソッドを呼び出す、ヘルパー関数を準備しているわけです。

今回のケースも同様にヘルパー関数をつくってあげれば良さそうです。

/**
 * お天気情報を出力するテンプレートタグ.
 */
function the_otenki() {
    global $otenki;

    $otenki->output();
}

以上の、クラス定義、アクションフックの登録、ヘルパー関数がかかれたプラグインファイルが otenki.php とすると、動作シーケンスの概要は次のようになります。

otenki_seq

本来は記事の公開(do_action(‘publish_post’))とテーマ出力処理は同時には起きえませんが、この図では一緒に書いております。逆にこの動きを理解することで、1アクセス内で発生する順次処理の結果を、クラスのインスタンスに保持し、合成した結果を出すような処理もつくることができるでしょう。

というわけで、なかなかプラグインが完成しませんが、、また明日。 🙂


目次

本連載はファイルがない状態からソースコードを実装していく方式を採っています。プログラムの構成法も含めて解説していますので、最初から読んでいくとより理解しやすいでしょう。

アクションフックのプラグインをつくる編
最初に、WordPress の拡張において重要なフックの考え方を、サンプルの動作のひとつである「記事公開時の処理追加」の実装を元に解説します。フックはこの後の画面出力、処理の非同期化や管理画面の付与でも使われていきます。
処理のクラス化(この記事)
WordPress 拡張におけるモジュール設計として、PHP のクラスを用いた方法を紹介します。分かりやすく、他のモジュールとの競合を最小限に抑えられる手法です。
外部 API の呼び出し
LWWS などの REST API に対して WordPress からリクエストを送る解説です。また、ユーザによって設定が異なる値がある場合のモジュール構成も合わせて紹介します。
外部 API 呼び出しの非同期化
外的要因などで処理スピードの低下が懸念される場合の処理方法です。WP-Cron を用いたスケジュール化手法を解説しています。
テンプレートファイルからの情報出力
テンプレートファイルに処理を記述し出力する場合に、拡張モジュールと疎結合にする実装法を紹介します。アクションフックの活用例としても有効です。
管理画面をつける
管理画面に設定欄を設けユーザが拡張の機能をコントロールできるようにする手法の解説です。また、本連載中のソースコードに最終的なリファクタリングをかけ、他の開発者にこの拡張の意味を表現するプログラミングテクニックも解説します。
まとめ
本連載の概要とまとめ、そして目次です。

WordPress 徹底解析(アクションフックのプラグインをつくる編)

「WordPress 徹底解析」シリーズです。

異常に忙しくなったり体の調子を悪くしてみたりで、できていなくてごめんなさい。がんばろう。というわけで、お久しぶりです!

なので脈略がなくなってきましたが「アクションフックのプラグインをつくる編」やってみまます。 🙂


アクションフック

前回書きました「WordPress 徹底解析(カスタマイズとフィルターとアクション編)」からアクショフックの実例になります。

WordPress 徹底解析(カスタマイズとフィルターとアクション編)

アクションの代表例はテンプレートファイルに記述する wp_head() や wp_footer() です。 これらを記述した部分にコアやプラグインから必要な HTML などが出力されているのはアクションフックの力です。 wp_head や wp_footer が動作したタイミングに合わせて、それぞれの処理が HTML タグを出力しています。

今回は、wp-otenki というプラグインのソースコードを元にアクションフックを解説してみようと思います。

これは、記事の公開時にライブドアの「お天気Webサービス(LWWS)」に問い合わせを行い、記事の書いた日にお天気情報を付与するプラグインです。

実はこのプラグイン 2006年に初版がかかれたもので、このたびついにライブドア側の API の変更で動かなくなったというお知らせを頂き、せっかくですので近代 WordPress に合わせて完全リライトしてみることにした次第です。(wp-cron がまだなくて自前で fsockopen してバックグラウンド処理していたくらい古かったです・・・)

プラグインの仕様は以下のようになります。

  • 「記事の公開時」にその日のお天気を LWWS API に問い合わせカスタムフィールドに格納する。
  • 格納されたお天気情報をテンプレートファイルの記述でアイコン出力する。

「記事の公開時」というタイミング。タイミングへの処理の追加といえばアクションフックの登場です。

アクションフックを用いると、さまざまな WordPress の動作(アクション)に対して、プラグインやテーマの functions.php に定義したコールバック関数(フック)で独自の追加処理を行うことが出来ます。

(フック)と注釈を書く場所に迷ってしまいましたが、、なんだろう、、「引っかける」という意味合いでしょうか。「デバッガを引っかける」とかぼくらの世界でよく言いますが、外部から中身(ここでは WordPress 本体)をいじらずに処理を乗っ取るとか追加するとかそういうイメージの言葉だと思います。

WordPress ではおおよそ考えられるほとんどの動作にフックができるようになっており、たとえば、<head>の出力時、WordPress の初期化終了時、テンプレートファイルへの処理移動時、記事保存前、記事保存時、管理画面の一覧カラム表示時、、等々等々・・・。いくらでも思いつきます。

どのようなアクションフックがあるかは codex から知ることができます。

プラグイン API/アクションフック一覧

この記事は(おそらくほぼ完全な)アクションフックの一覧です。アクションフックはバージョン2.1以降から、プラグインおよびテーマ開発時に利用できるようになっています。詳しい情報については下記もご覧下さい。

さて、アクションに処理(関数)を定義するには、WordPressの API 関数「add_action」を用います。また、直接使う機会は少ないかもしれませんが、その呼び出し元となる関数は「do_action」です。

add_action 関数に指定する引数のアクション名で、どの場合の動作に処理の追加を行うのかが決定されます。

フックはプラグインや functions.php での拡張向け機能として存在しているだけではなく、 WordPress 本体の機能でも数多く使われいます。

たとえば、サイトの <head> 部分に主に HTML を挿入する働きを担うアクション名「wp_head」フックだけに注目すると WordPress は以下のようなシーケンスで動作します。

action_hook_new

図中、add_action の 3引数目は関数呼出し順の優先度(プライオリティー)になります。同一アクション名に複数の関数が登録されている場合は、この値が少ない方から呼び出しが開始され、無指定の場合は 10 という値が使われます。

関数2、関数3 が登録順ではなくプライオリティー順で呼び出されていることに注目してください。処理順で不具合が起きる場合は、この値を調整することで呼出し順をコントロールすることができます。

ユーザがフックを活用する場合は、プラグインや functions.php に処理を行う関数を定義し、事前に add_action を用いてその関数を追加する、というのが大きなつくりかたの流れです。あとは、そのタイミングになれば自動的に WordPress が do_action を契機に登録された関数を呼び出してくれます。

では wp_head アクションフックの場合、契機となる do_action(‘wp_head’); を呼出してしているのは WordPress 本体のどこかを調査してみます。

wp-includes/general-template.php

/**
 * Fire the wp_head action
 *
 * @since 1.2.0
 * @uses do_action() Calls 'wp_head' hook.
 */
function wp_head() {
    do_action('wp_head');
}

wp_head() テンプレートタグ。

[tegaki]欧米か![/tegaki]

・・・言ってみたかっただけです。すいません。。

ということで wp_head アクションフックは、単純にテンプレートファイルの header.php にかくことになっている wp_head() テンプレートタグが do_action を呼び出しているのでした。

この場合は自分で do_action 呼び出しているのに近い感じですが、、多くのフックは WordPress によってひっそりと呼ばれております。

記事公開のフック

さて、今回つくりたいプラグインは「記事公開時」に「お天気取得処理」を追加したいということで、codex からそれっぽいアクション名を探します。

このような場合は、管理画面から公開ボタンを押した、ドラフト状態の記事を更新ボタンから公開した、xmlrpc 経由で記事を投稿した等に呼び出されれる「publish_post」 アクションが使えそうです。

処理を追加したいアクション名が分かれば、実装開始です。

プラグインファイル(もしくは functions.php)に以下の記述をしてみましょう。(プラグインヘッダコメントは省略しています)

function prepare($post_ID, $post) {
    die("test");
}

add_action('publish_post', 'prepare', 10, 2);

prepare は任意の関数名で、function で定義した関数を add_action(‘publish_post’, ‘prepare’ として登録しています。

とりあえずこれで、管理画面から公開ボタンを押すと「test」という真っ白画面が登場してくると思います。処理をのっとった!、、勝利の確信の瞬間です(笑) die(); しているので、思ったタイミングで落ちれば正解です。まずは関数が呼ばれることを確認するのがアクションフックをかく第一歩です。

add_action('publish_post', 'prepare', /*ここ→*/10, 2);

ソースコード中、add_action 関数の3番目引数(10)が先ほどでてきた同一フックに対する実行順を決定するプライオリティーです。今回のプラグインはいつ呼ばれても良くデフォルト値(10)で本来は省略できるのですが、、次の引数(2)を指定したかったのでしょうがなく書いています。

add_action('publish_post', 'prepare', 10, /*ここ→*/2);

問題の4番目引数(2)は、登録した関数に渡される引数の数になります。「prepare($post_ID, $post)」の個数である 2 が該当します。デフォルトは1で、指定しない場合は $post_ID だけ渡されるイメージです。

function prepare(/*ここと→*/$post_ID, /*ここ→*/$post) {

アクションフックの中にはこのように、関数の呼び出しとともに、さらに詳細な情報を引数で渡してくれるアクションもあります。 publish_post では、どの記事が公開されたかという情報を引数の $post_ID(記事ID) と $post(記事オブジェクト) で得ることができます。

このような引数をどのように調査すればいいかといえば、ソースコードをみるのが早くて正確です。ここまで読んでいただいた方ならお察しの通り、do_action( ‘publish_post’ で WordPress 内のファイルを検索すればでてくるってのが正解!なのですが、publish_post には若干のトリックがあります。

wp-includes/post.php

function wp_publish_post( $post ) {
    // 略
    wp_transition_post_status( 'publish', $old_status, $post );
    // 略
}

function wp_transition_post_status($new_status, $old_status, $post) {
    do_action('transition_post_status', $new_status, $old_status, $post);
    do_action("{$old_status}_to_{$new_status}", $post);
    do_action("{$new_status}_{$post->post_type}", $post->ID, $post);
}

do_action は、一番下の行「do_action(“{$new_status}_{$post->post_type}”, $post->ID, $post)」が該当します。残念ながら、変数で動的にアクション名をつくっているので、検索ででてこないのでした。

do_action("{$new_status}_{$post->post_type}", $post->ID, $post);

呼び出し元 wp_publish_post 関数。

wp_transition_post_status( 'publish', $old_status, $post );

第一引数が publish で、記事の投稿タイプは post なので、wp_transition_post_status 関数内の do_action で結合して publish_post となります。後ろに「$post->ID, $post」が続き、フックに登録した関数で情報が取得できることが分かります。

do_action("{$new_status}_{$post->post_type}", $post->ID, $post);

このようにソースコードをみることで、ついでに publish_page や publish_[カスタム投稿タイプ名]や、publish -> draft などのステータスの変更などもフックで「引っかけられる」ことも学ぶことが出来ました。:)

do_action('transition_post_status', $new_status, $old_status, $post);
do_action("{$old_status}_to_{$new_status}", $post);

この辺は、WordPress を少しやってくれば経験的に「こうなっているんではないか」という予測がつくようになってきます。WordPress の恐るべきは、それが大抵予測通りなところです。IDE などの関数呼び出し元ジャンプ機能を使ってみていけば、すぐお望みのものが見つかるハズです。

てなわけで、再度プラグインのソースコードに戻ります。

function prepare($post_ID, $post) {
    die("test");
}

add_action('publish_post', 'prepare', 10, 2);

この処理は、PHP 5.3 の無名関数を使うと次のようにもかくことができます。関数名削除。

add_action('publish_post', function($post_ID, $post) {
    die("test");
}, 10, 2);

jQuery みたいで便利ですね。

関数名考えなくて済みますので、PHP 5.3 が使える環境の方は是非。プラグインや functions.php で定義する関数はグローバル領域となってしまいますので、関数名かぶりを考えないと意味でも楽ができます。 🙂

さて、ここまでいけば後はお天気 API に問い合わせをして、カスタムフィールドに格納する処理を関数に書けば良いです。

add_action('publish_post', function($post_ID, $post) {
    // "今日"のポストの時だけ天気を取得
    if(date("Y/m/d", strtotime($post->post_date)) != date("Y/m/d")) return;
    // LWWS(V1/JSON)より天気情報(札幌)を取得
    $json = file_get_contents(
        'http://weather.livedoor.com/forecast/webservice/json/v1?'
        . http_build_query(array('city' => '016010')));
    // 正常な JSON 形式であればカスタムフィールドに格納
    // 取得できなかった場合は次回の公開に期待
    if($json !== false && json_decode($json) !== null) {
        update_post_meta(
            $post_ID
            , 'otenki'
            , $json);
    }
}, 10, 2);

API からもらえるお天気情報は過去日が取得できず現在日以降になります。処理上のポイントは「”今日”のポストの時だけ天気を取得」の部分で、アクションフックからもらった $post 記事オブジェクトの情報を元に「今日」日付の公開記事のみを取得するようにしています。過去日の公開では天気は取得しません。

余談ですが WordPress の未来日の予約投稿は、実際にその日になった時に公開処理が行われます。これは WordPress に内蔵されるスケジューラの力によるものです。

さて、ここまでつくってみたものの、このままではプラグインの体をなしていません。札幌しかお天気とれないし、、サイト用にカスタムフィールドから HTML タグを出力する処理もありません。また、記事の公開と同じシーケンスで外部 API に対して通信取得処理を行っているため、若干公開処理が遅くなると言う弊害もあります。

というわけで、次回(明日予定)はこれらの対応と、プラグインの class 化によるクリーンナップや、管理画面をつけてみたりしたいと思います。 お楽しみに!

忘れていました。。すいません。。すいません、、こちらも次回に。 🙂


目次

本連載はファイルがない状態からソースコードを実装していく方式を採っています。プログラムの構成法も含めて解説していますので、最初から読んでいくとより理解しやすいでしょう。

アクションフックのプラグインをつくる編(この記事)
最初に、WordPress の拡張において重要なフックの考え方を、サンプルの動作のひとつである「記事公開時の処理追加」の実装を元に解説します。フックはこの後の画面出力、処理の非同期化や管理画面の付与でも使われていきます。
処理のクラス化
WordPress 拡張におけるモジュール設計として、PHP のクラスを用いた方法を紹介します。分かりやすく、他のモジュールとの競合を最小限に抑えられる手法です。
外部 API の呼び出し
LWWS などの REST API に対して WordPress からリクエストを送る解説です。また、ユーザによって設定が異なる値がある場合のモジュール構成も合わせて紹介します。
外部 API 呼び出しの非同期化
外的要因などで処理スピードの低下が懸念される場合の処理方法です。WP-Cron を用いたスケジュール化手法を解説しています。
テンプレートファイルからの情報出力
テンプレートファイルに処理を記述し出力する場合に、拡張モジュールと疎結合にする実装法を紹介します。アクションフックの活用例としても有効です。
管理画面をつける
管理画面に設定欄を設けユーザが拡張の機能をコントロールできるようにする手法の解説です。また、本連載中のソースコードに最終的なリファクタリングをかけ、他の開発者にこの拡張の意味を表現するプログラミングテクニックも解説します。
まとめ
本連載の概要とまとめ、そして目次です。

ダウンロードしたツイート CSV を Groovy + OrientDB で抽出

ワンショットではあるものの大きめのデータを処理する場合、データベースに入れたらいいなぁとおもいつつも、データベースサーバ起動するのが面倒だったり create table するのが面倒だったりすることがよくあります。

そんな時は組み込み可能な DB ってことで、こんなことに使ったら怒られそうではありますが OrientDB と Groovy の組み合わせ。タイムリーにも Twitter の自分の全ツイートが取得可能となったということで抽出をかけてみました。 🙂

OrientDB Graph-Document NoSQL dbms

OrientDB is an Open Source NoSQL DBMS with both the features of Document and Graph DBMSs. It’s written in Java and it’s amazing fast: can store up to 150,000 records per second on common hardware.

#もちろん OrientDB はサーバモードもありますです。

Twitter の全ツイートダウンロードですが、「ユーザ情報」の下の方にあるリクエストボタンをクリックするとメールリンクで CSV が送られてくるようです。

130326-0003

とりあえず Eclipse にファイルやライブラリを配置して・・・。(./file/Tweets は OrientDB によってつくられた DB の物理ファイルです)

130326-0001

まずは CSV2OrientDB のローダをかきました。 TweetsLoader.groovy

import au.com.bytecode.opencsv.CSVReader
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx
import com.orientechnologies.orient.core.record.impl.ODocument

// define CSV header (exclude expanded_urls)
def header = [
    &quot;tweet_id&quot;
    ,&quot;in_reply_to_status_id&quot;
    ,&quot;in_reply_to_user_id&quot;
    ,&quot;retweeted_status_id&quot;
    ,&quot;retweeted_status_user_id&quot;
    ,&quot;timestamp&quot;
    ,&quot;source&quot;
    ,&quot;text&quot;]

// load CSV
CSVReader reader = new CSVReader(new FileReader(&quot;./file/tweets.csv&quot;))
List myEntries = reader.readAll()
reader.close()

// create OrientDB
ODatabaseDocumentTx db =
    new ODatabaseDocumentTx(&quot;local:./file/Tweets&quot;).create()

// import CSV
myEntries.each {
    ODocument doc = new ODocument(&quot;Tweet&quot;);
    def index = 0
    header.each { name ->
        doc.field(name, it[index])
        index++
    }
    doc.save()
}

// close OrientDB
db.close();

これを実行すると .csv が “local:./file/Tweets” DB に読み込まれます。スキーマレスなので適当にロードできます。お手軽。 🙂

でもって、できたデータベースにクエリーを発行します。 Groovy が入っているつぶやきを単純に like にて。 TweetsQuery.groogy

import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx
import com.orientechnologies.orient.core.record.impl.ODocument
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery

// open OrientDB
ODatabaseDocumentTx db =
    new ODatabaseDocumentTx(
        &quot;local:./file/Tweets&quot;).open(&quot;admin&quot;, &quot;admin&quot;);

// query
List<ODocument> result = db.query(
    new OSQLSynchQuery<ODocument>(
        &quot;select * from Tweet where text like '%Groovy%'&quot;));

// output
result.each {
    println it.field(&quot;text&quot;)
}

// close OrientDB
db.close();

手抜きコード申し訳ない(笑)

という感じで実行結果です。 あとは煮るなり焼くなりできますね。

130326-0002

なんだか懐かしいツイートがいっぱいでてきました。。

ちなみに5万弱のレコード数でしたが、それぞれの処理は待つ暇なく終わっています。

ワンショットとはいえ、普通のサーバ型の RDBMS を使ってしまうとプロジェクトだけでアプリを管理できずポータブル性がなくなってしまいますので組み込みDBの形式は便利ですね。サーバの起動にやきもきすることもありません。

また、OrientDB はドキュメント型ということで、スキーマレスで扱えるのもこういった用途に気軽で良いです。 このソースでは手抜きしていますが、POJO へのマッピングもできますのできちんとかくこともできます。

なんだかものすごいプロダクトをこんなことに使っていいんだろうか、、とも思ってしまいますが、、使い方のひとつということでお許しを。。 🙂