ラベル Mac の投稿を表示しています。 すべての投稿を表示
ラベル Mac の投稿を表示しています。 すべての投稿を表示

2014年4月29日火曜日

libGDX のプレゼン資料

4月28日にイスタンブールで行われた Istanbul Tech Talk にて、 Mario Zechner が発表した libGDX についてのプレゼン資料です
また、資料中にある Live-Coding Session に使用したコードは GitHub 上にて公開されています
各実装フェーズ毎にタグが切ってあり、また script.txt にその簡単な解説があるため、 libGDX にてどのように実装を行うかを把握するにはよい資料だと思います
(全体を把握しやすくするため、実装はかなりコンパクトにまとまっています)

2014年4月26日土曜日

libGDX のプロジェクト構成と共通インターフェイスについて

libGDX はマルチプラットフォーム対応のため、(プラットフォーム共通の)ゲームロジックの実装と、各プラットフォームに依存する実装は分離されています
セットアップツールを使い、プロジェクトを作成すると以下のようなディレクトリ構造にてプロジェクトが作成されます
(セットアップツールの "suprojects" の設定にて、 "Desktop" 、 "Android" 、 "Ios" 、 "Html" の4つすべてを選択した場合になります)

"android"、 "desktop" 、 "html" 、 "ios" の各ディレクトリには、それぞれのプラットフォーム毎の実装、設定などを含みます
例えば、 "android" ディレクトリには "AndroidManifest.xml" ファイル、 "ios" ディレクトリには "Info.plist.xml" ファイルなどがあります


これらのプラットフォームの違いを吸収するため、 libGDX は次の5つのインターフェイスを用意しています
  • Application … ライフサイクル、ウィンドウ管理などのアプリケーションレベルイベントインターフェイス
  • Files … ファイルシステムインターフェイス
  • Input … マウス、キーボード、タッチイベントや加速度センサーなどの入力イベントインターフェイス
  • Net … HTTP(S) 、 Socket 通信などのネットワークインターフェイス
  • Audio … PCM 入出力などのオーディオインターフェイス
  • Graphics … OpenGL ES 2.0、3.0 インターフェイス
これらのインターフェイスを利用することで、開発者は個々のプラットフォームの差を意識することなく、実装を行うことができます
なお、プラットフォームによっては提供されていない機能や未実装の機能(2014年4月現在では iOS プラットフォームではコンパスが利用できないなど)が存在するため、すべての機能が共通して利用できるというわけではないので、ご注意ください

2014年4月1日火曜日

libGDX について

libGDX は、デスクトップ(Windows, Mac OS X, Linux)、モバイル(Android, iOS, Blackberry)、 HTML5 というマルチプラットフォームをサポートした、オープンソース(Apache License 2.0) の Java ゲーム(2D / 3D)開発フレームワークになります
国内ではまだ有名とは言えない状況ですが、海外では Android ネイティブアプリケーションをはじめ、多くのゲーム開発にて採用されています

このフレームワークの最大の魅力は、ラピッドプロトタイピングと、それによりイテレーションを素早く実行できることにあります
実行、デバッグが容易なデスクトップ用アプリケーションとして開発を進め、その後各プラットフォームにて調整という流れで作業を行うことで開発時間の短縮がはかれます
(ただし、 HTML5 対応に限っては調整にかなりの時間を要するかと思います)

また他のゲーム開発用フレームワークと比較すると、 libGDX は OpenGL による描画や入出力処理などの低レベル API が中心として提供され、ゲーム開発によく使われるトランジションなどの高レベル API はあまり用意されていません
しかし、これにより他のライブラリ、フレームワークとの柔軟な組み合わせ(例えば、先述のトランジションに関しては Universal Tween Engine を使用するなど)を実現することができます

ドキュメントに関しても公式の Wiki 、フォーラムをはじめ、などが充実しています(残念ながら、日本語の資料は少ないです)
YouTube 上にも(公式のものではありませんが)チュートリアル動画がいくつかアップロードされています(以下はシリーズとしてまとまっているものを挙げています)
日本語の資料は少ないのですが、 @rnkv さんの「技情研ネット」内のページがとても実践的な内容にてまとまっています
以上、簡単な libGDX の紹介と資料のリンクまとめになります
(上記以外にもオススメのドキュメント等ありましたら教えてください)

2014年3月30日日曜日

NetBeans で libGDX プロジェクトを作成する

NetBeans で libGDX プロジェクトを作成する方法を紹介します
libGDX は Java 用クロスプラットフォームゲーム開発フレームワークで、現在 Windows, Mac, Linux, Android, iOS, BlackBerry, HTML5 をサポートしています
今までは開発には Eclipse を推奨していたこともあり、他の IDE にて開発するのは少し手間が必要でした
今回新たにセットアップツールの刷新が行われ、ビルドツールとして gradle が採用されたことにより、 NetBeans をはじめ、 Eclipse 以外の IDE 、エディタによる開発が簡単に行うことができるようになりました
本エントリでは、この新しいセットアップツールと、 NetBeans での libGDX プロジェクトの作成方法を紹介したいと思います
なお、 libGDX は現在も活発に開発が進められているプロジェクトであるため、閲覧される時点では挙動が異なる可能性があることをご了承ください
今回使用した環境は以下の通りになります

OS: Mac OS X 10.9.2
JDK: 1.7.0_51
Xcode: 5.1
※ Xcode は iOS プラットフォーム利用時のみ必要となります
NetBeans 8.0(Build 201403101706)
Gradle Support Plugin 1.3.0

まず、セットアップツールをダウンロードします
適当な場所に保存後、下記コマンドにてセットアップツール起動します

$ java -jar gdx-setup.jar

起動後、上記のようなウィンドウが表示されるので、各項目に適当な値を入力します
(※4月23日最新版セットアップツールに更新)

Name … アプリケーション名
Package … 作成するプロジェクトのパッケージ名
Game class … プラットフォーム共通(core)のメインゲームクラス名
Destination … プロジェクト作成先ディレクトリ
Android SDK … Android SDK のパス(local.properties に設定されます)

"Sub Project"、"Extensions" については必要に応じ、チェックを行ってください
入力後、 "Generate" ボタンをクリックすると、プロジェクトが "Destination" フィールドに指定した場所に生成されます

次に作成したプロジェクトを NetBeans で開きます
「ファイル > プロジェクトを開く」にて、生成されたディレクトリまで移動します


プロジェクトを開くと、以下のようなツリー構造で NetBeans に開かれます


作成したプロジェクト(ルートプロジェクト)は、5つのサブプロジェクトで構成されます

android … Android 用プロジェクト
core … プラットフォーム共通プロジェクト
desktop … デスクトップ (Windows, Mac, Linux) 用プロジェクト
gwt … HTML5(GWT) 用プロジェクト
ios … iOS 用プロジェクト

各サブプロジェクトはダブルクリックすることで開くことができます
まず、ルートプロジェクトの設定を行います
(ルートプロジェクトに行った設定はすべてのサブプロジェクトに反映されます)
ルートプロジェクトを右クリックし、コンテキストメニューから "プロパティ" を選択すると以下のようなウィンドウが表示されます



"Gradle home" の "Inherit" チェックボックスをはずします
また、テキストボックスに値が入力されている場合は、それも削除し、空白の状態にします
お使いの環境が Mac で、 JDK に Java 8 を使用されている場合は "Platform for build scripts"、"Target platform"、"Source Level" にて Java 7 (1.7) を選択してください
(デスクトップ用プロジェクトに使用されている lwjgl が2014年3月29日時点で Java 8 に対応していないため)
上記設定が終わったら、"OK" ボタンをクリックし、設定を反映します

プロジェクトの設定が終わったので、各サブプロジェクトを実行してみます
最初はデスクトップ用アプリケーションを実行します
サブプロジェクト内の desktop をダブルクリックして開きます
開いたプロジェクトを右クリックし、表示されたコンテキスト内から「Tasks > run」と選択し、クリックします


ビルドが実行され、以下のようなウィンドウが表示されます

次に Android 用アプリケーションを起動します
実行するために事前に端末の接続、またはエミュレータの準備を事前に行っていてください
今回は Genymotion を実行環境として使用します
サブプロジェクト内の android をダブルクリックして開きます
開いたプロジェクトを右クリックし、表示されたコンテキスト内から「Tasks > installDebug」と選択し、クリックします
Android 用のタスクは量が多いため、表示できていない場合は「Custom Tasks > Custom Tasks」と選択し、表示された "Execute Custom Tasks" ウィンドウの "Tasks" フィールドに "installDebug" と入力し、 "Execute" ボタンをクリックすることで同様に実行することができます
("Save And Execute" ボタンをクリックすると、実行したタスクが保存されるため、2回目以降は入力の手間が省けます)


ビルドが実行され、接続していた端末、またはエミュレータにアプリケーションがインストールされます
実行すると以下のように表示されるかと思います


次は HTML5 (GWT) 用アプリケーションを起動します
サブプロジェクト内の android をダブルクリックして開きます
開いたプロジェクトを右クリックし、表示されたコンテキスト内から「Tasks > superDev」と選択し、クリックします
(リスト内に "gwtSuperDev" という似た名前のタスクがありますが、こちらでは正常に起動できませんので、間違えないようご注意ください)


次にブラウザを開き、 "http://localhost:9876/" へアクセスします
(制限はないのですが、 Google Chrome ブラウザの使用をおすすめします)
以下のような表示がされるので、"Dev Mode On"、"Dev Mode Off" をブックマークレットとしてブックマークバーに登録ください


次に "http://localhost:8080/gwt/" へアクセスします
最初に以下のようなダイアログが表示されますので、先ほど登録した "Dev Mode On" ブックマークレットを実行します


実行すると、以下のように表示されるので、 "Compile" ボタンをクリックします


コンパイル終了後、以下のように表示されます
(再度先ほどのダイアログが出る場合がありますが、ローディングが終わるまでお待ちください)


最後に iOS 用アプリケーションを起動します
サブプロジェクト内の ios をダブルクリックして開きます
開いたプロジェクトを右クリックし、表示されたコンテキスト内から「Build」を選択し、クリックします
ビルド終了後、再度プロジェクトを右クリックし、「Tasks > launchiPhoneSimulator」と選択し、クリックします
(今回は iPhone シミュレータでの実行を行いますが、 iPad シミュレータ、および実機での実行も可能です)


実行後、以下のように表示されます
(初回実行時はシミュレータ起動までかなり時間が掛かりますのでご注意ください)


以上が、サポートする各プラットフォームでの実行となります
新しいセットアップツールと gradle を使用することで、簡単に NetBeans 上にプロジェクト構築が出来ることをご理解頂けたかと思います

実際のゲーム開発は、サブプロジェクトにあった core (プラットフォーム共通)プロジェクトを中心に実装していくことになります
libGDX を使用したゲーム開発の詳細については、また別のエントリにて紹介できればと思います

2014年2月1日土曜日

iPhone Game Blueprints を読みました

Packt Publishing の "iPhone Game Blueprints" のレビューです

本書は iPhone ゲームを開発する上でのゲームデザインと App Store での売り出し方について解説した書籍です
目次は下記のようになっています

  • Preface
  • Chapter 1: Starting the Game
  • Chapter 2: Ergonomics
  • Chapter 3: Gesture Games
  • Chapter 4: Card and Board Games
  • Chapter 5: Puzzles
  • Chapter 6: Platformer
  • Chapter 7: Adventure
  • Chapter 8: Action Games
  • Chapter 9: Games with Reality

前半はゲームをつくる前段階として注意すべき点について記述されています
ここで取り扱われている内容は iPhone ゲーム開発に限らず、他のプラットフォームでも役立つ内容だと思います
(iPhone 固有の注意点もしっかり書かれています)
ただ、扱っている範囲が広いため、やや物足りないものもあり、それらについては別の書籍にて補完していく必要があるかと思います

後半は、前半にて取り扱ったポイントをさらにゲームのジャンルごとに掘り下げています
各ジャンルにて、基本なアイディア(技術的なベース)を説明し、そこからどのように魅力的なゲームとなるようアイディアを広げるかを、いくつかのサンプルとなるアイディアをベースに解説しています

読んだ感想としては、アイディア出しから App Store へのリリースまでの長い行程を網羅的に書かれた良書でした
一点注意いただきたいのは、本書では実装(プログラミング)については扱われていないということです
そういった内容を期待される場合は別のゲーム開発に関する書籍(日本語の書籍も数多く存在します)を参考にされるのがいいかと思います
反対に、いくつかの書籍、チュートリアルを終えたが、いざゼロからゲーム開発を行おうとした際に何から手を付けていいのか詰まっている方の強力な後押しになるものと思います
ページ数はやや多いものの、イラストや画面イメージが多用されていることもあり、詰まることなく読み進めることができました

興味を持たれた方は、上記サイトから Chapter 04 がサンプルとしてダウンロードできますので、確認してみてはいかがでしょうか

2014年1月19日日曜日

NetBeans と RoboVM で iOS アプリ開発(Gradle 編)

前回に引き続き、 NetBeans と RoboVM で iOS アプリ開発を行う方法についてです
今回は Gradle を使用した開発を紹介します
Gradle プラグインは公式では提供されていませんので、拙作のプラグインを利用します
使用する環境は以下の通りです

OS: Mac OS X 10.9.1
Xcode: 5.0.2
NetBeans: 7.4 (Build 201310111528)

まず、使用する環境に Gradle をインストールします
以下の例では、 Homebrew を使用してインストールを行っています

$ brew install gradle


次に NetBeans に Gradle Support プラグインをインストールします


拙作のサンプルアプリケーションのリポジトリを clone します
このサンプルアプリケーションは、公式のサンプルアプリケーションを Gradle 対応に変更したプロジェクトになります


clone 後、 Gradle wrapper を利用するため、プロジェクトのプロパティを開き、以下のように「Gradle home」のフィールドを空白に設定します


設定後、実際に動かしてみます
Gradle プラグインのタスクは下記の通りになっています
  1. launchIPhoneSimulator … iPhone シミュレータにて実行
  2. launchIPadSimulator … iPad シミュレータにて実行
  3. launchIOSDevice … 実機にて実行(要プロビジョニング済)
  4. createIPA … ipa ファイル生成
今回は Maven プラグインのときと同様に iPhone シミュレータにて実行します
プロジェクトのコンテキストメニューから「Tasks」>「launchIPhoneSimulator」を実行します


初回実行時はビルドに時間が掛かりますが、完了後以下のように iPhone シミュレータが起動します


Maven 、 Gradle を利用した RoboVM による iOS アプリケーション開発ということで前回、今回と紹介してきました
今後、 RoboVM についてより詳しい紹介を行えたらと思います

2014年1月18日土曜日

NetBeans と RoboVM で iOS アプリ開発(Maven 編)

NetBeans と RoboVM で iOS アプリ開発を行う方法について紹介します

まず、 RoboVM についてですが、 Java にて iOS 用ネイティブアプリケーションを作成することができるコンパイラ、およびライブラリとなります
(詳細は公式ページ等を参照ください)

RoboVM コミュニティでは上述のコンパイラ、ライブラリに加え、 Maven 用プラグイン、 Eclipse 用プラグインが配布されていますが、残念ながらNetBeans 用プラグインはありません
NetBeans にて RoboVM を利用するにはいくつか方法がありますが、 Maven プラグインを使用する方法が最も簡単かと思います

Maven プラグインの使い方を、サンプルアプリケーションを使って解説します
使用する環境は以下の通りです

OS: Mac OS X 10.9.1
Xcode: 5.0.2
NetBeans: 7.4 (Build 201310111528)

まず、 github にある RoboVM サンプルアプリケーションのリポジトリを cloneします
clone 後、最新の RoboVM 、 Maven プラグインを利用するために pom.xml を編集します
2014年1月18日現在、最新の RoboVM のバージョンは "0.0.8"、 Maven プラグインのバージョンは "0.0.8.1"になるので、以下の2カ所を修正します
<plugin>
  <groupId>org.robovm</groupId>
  <artifactId>robovm-maven-plugin</artifactId>
  <version>0.0.8.1</version>
  <configuration>
    <config>
      <mainClass>org.robovm.sample.ios.RoboVMSampleIOSApp</mainClass>
      <os>ios</os>
      <arch>x86</arch>
    </config>
  </configuration>
</plugin>

<dependency&gt
  <groupId>org.robovm</groupId>
  <artifactId>robovm-rt</artifactId>
  <version>0.0.8</version>
</dependency>
<dependency>
  <groupId>org.robovm</groupId>
  <artifactId>robovm-cocoatouch</artifactId>
  <version>0.0.8</version>
</dependency>

設定後、実際に動かしてみます
Maven プラグインのゴールは下記の通りになっています
  1. robovm:iphone-sim … iPhone シミュレータにて実行
  2. robovm:ipad-sim … iPad シミュレータにて実行
  3. robovm:ios-device … 実機にて実行(要プロビジョニング済)
  4. robovm:create-ipa … ipa ファイル生成
今回は iPhone シミュレータにて実行します
コンテキストメニューより「カスタム」>「ゴール...」を選択します


表示されたウィンドウにて、"robovm:iphone-sim" を入力し、「OK」ボタンをクリックします


初回実行時はビルドに時間が掛かりますが、完了後以下のように iPhone シミュレータが起動します


RoboVM はまだ開発途上のプロダクトですが、ゲーム開発などパフォーマンスが要求されるような場面でも十分に使用できるレベルまでになっていると思います
Java + RoboVM + NetBeans にて iOS アプリケーション開発に挑戦してみてはいかがでしょうか

2012年1月7日土曜日

NetBeans IDE 7.1 リリース

NetBeans IDE 7.1 がリリースされました
ダウンロードはコチラからできるようになっております
7.1 にて追加された新機能に関しては、コチラを参照ください
また、 Mac 用ニーモニック除去バージョンの7.1用日本語パックはコチラからダウンロードできます

恒例のスプラッシュです


今回、個人的な目玉新機能はやはり Git サポートです
github でのアウトプットも定着した昨今では、やはりありがたい新機能です
近日中にこの機能について紹介できたらと思います

これ以外にも JavaFX 2.0 サポート、 CSS3 サポート、 PHP 開発者には嬉しい Smarty サポートなどの機能追加も行われています

不具合等、何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2012年1月1日日曜日

2012年やりたいこと

昨年後半はいろいろと個人的にバタバタしたため、ブログの更新もほとんどできていませんでした
(NetBeans 7.1 も RC2 まで現在リリースされていますが、ご紹介できていない状態ですし…)
今年は少し余裕ができるのではという感じなので、ブログも含め、以下のことを中心に学習、アウトプットをしていきたいと思っています
(宣言的に書かないと、そのままダラダラと流されそうなので…)

・ NetBeans の機能紹介
・ OrientDB を中心とする GraphDB 関連について
・ ネットワークなど、過去見送ってきた基礎知識に関しての学習記録
・ NetBeans 用プラグインの開発について
・ Scala や Python 、 PHP などについて

とにかく、継続してアウトプットすることを頑張りたいと思います
まずは、今月上旬には 7.1 が正式にリリースされる予定なので、そちらについて紹介できればと思います
(7.1 以降のリリーススケジュールについては、 2012年1月1日現在では不明ですが…)

今年も本ブログを何卒、宜しくお願い致します

2011年10月4日火曜日

NetBeans IDE 7.1 Beta リリース

NetBeans IDE 7.1 Beta がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


今回のバージョンアップでは、 JavaFX 2.0 のサポートをはじめ、 Web アプリケーション開発では CSS3 のサポート、 PHP 開発では Smarty テンプレートサポート、Git サポートの追加などがあります
その他の追加機能や各詳細はリリースノートを参照ください

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年8月3日水曜日

NetBeans IDE 7.0.1 リリース

NetBeans IDE 7.0.1 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


今回は、先日リリースされた Java SE 7 の完全対応がメインとなっています
その他には、同梱されている Glassfish のバージョンがあがっていること、いくつかのバグフィックスがなされていることなどがあります

現在、7.0 をお使いの方は、自動アップデートにて 7.0.1 相当になりますので、再インストールすることなく、アップグレードできます

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年4月21日木曜日

NetBeans IDE 7.0 リリース

当初の予定よりも遅くなりましたが、 NetBeans IDE 7.0 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


7.0 によって追加、または改善された主なポイントは以下のようになっています

・シンタックス、ヒントなどのエディタ拡張を含んだ、JDK 7 サポート
・WebLogic Application Server 、 GlassFish 3.1 サポートの改修
・Oracle Database サポートの改善
・HTML5 編集サポート
・Maven 3 サポートと IDE への同梱
・CDI、REST サービス、Java Persistence 、Bean Validation のサポート改善
・PHPリネームリファクタリング対応
・外部での変更検出の改善
・C/C++ サポートの更新

その他の機能については、 コチラを参照頂ければと思います

また、以前にも書いていますが、 7.0 より JUnit が同梱配布されなくなりましたので、 NetBeans 本体インストール後別途プラグインとしてのインストールが必要となります
手順は簡単ですので、詳細は以前のエントリを参考にして頂ければと思います

次回のリリースは、4月21日時点でのロードマップ上ではバージョン番号が7.0.1、リリース予定日が2011年の7月になっています
また、主要な実装機能もコチラにて掲載が始まっています
(バージョン番号からもわかる通り、メインはバグフィックスと JDK7 の対応強化となり、新機能追加の予定はないようです)

何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年4月12日火曜日

オープンソース NoSQL データベース OrientDB を使ってみる #3

前回の投稿から半年以上過ぎましたが、OrientDB の紹介3回目です
前の2回は以下の通りです

オープンソース NoSQL データベース OrientDB を使ってみる #1
オープンソース NoSQL データベース OrientDB を使ってみる #2

データ間の関連(リレーション)について紹介します
データ間の関連とは2つの異なるレコードを関連付けることで、データの透過的な参照や複雑なデータ構造の表現が可能となります

OrientDB では参照型( Referenced relationships )と組込型( Embedded relationships )という2種類の関連付けをサポートしています
参照型は、フィールドに対象レコードのレコードID(全レコードにてユニークとなるID)を持つことでデータ間の関連付けを行います
そのため、関連付ける各レコードは独立したレコードとして各々参照できる必要があります
対して組込型は、フィールドに直接レコードをそのものを設定するもので、組み込まれたレコードを独立して参照することはできません

また、参照、組込型として関連付けられるデータは 1:1 だけでなく、各々 List 、 Set 、 Map という 1:N 、または N:M の関係を作ることができます
(今回はこの部分の説明の詳細は省略させて頂きます)

それでは実際にデータの登録を行い、どのような構造のレコードが生成されるかを説明したいと思います
今回使用した環境は下記の通りです

・Mac OS X 10.6.7
・Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)
・OrientDB 0.9.25
・NetBeans 7.0 RC2

以降は上記環境にて、サーバの起動、専用クライアント(コンソール)の接続まで完了している前提で進めます
サーバやクライアントの起動方法、クライアントを使用したレコード操作などについては、前々回のエントリを参照ください
また、文中で使われるレコードIDは環境により異なりますので、お使いの環境にあわせて読み替えてください

まず、テストデータを登録するため、下記クエリを実行して Person クラスと Group クラスを作成します
( ">" はプロンプトとなりますので、コピーして実行する際にはご注意ください)
> create class Person
> create class Group
次に Group クラス のデータを登録します
> insert into Group (name) values ('Rebel Alliance')
> insert into Group (name) values ('Galactic Empire')
下記コマンドで Group クラスに2レコード登録されたことが確認できます
> browse class Group
---+--------+--------------------
  #| REC ID |NAME                
---+--------+--------------------
  0|    25:0|Rebel Alliance      
  1|    25:1|Galactic Empire     
---+--------+--------------------
"REC ID" は先の説明のレコードIDを指し、 "Rebel Alliance" は "25:0" 、 "Galactic Empire" は "25:1" のレコードIDを持つこととなります

次に参照型の関連フィールドを持つレコードを作成します
関連付けるレコードは先ほど登録した Group クラスのレコードです
下記クエリを実行して、 レコードを登録します
> insert into Person (name, surname, group) values ('Luke', 'Skywalker', 25:0)
> insert into Person (name, surname, group) values ('Han', 'Solo', 25:0)
> insert into Person (name, group) values ('Chewbacca', 25:0)
> insert into Person (name, surname, group) values ('Leia', 'Organa', 25:0)

> insert into Person (name, group) values ('Darth Sidious', 25:1)
> insert into Person (name, group) values ('Darth Vader', 25:1)
レコードに関連付けを設定する場合は、フィールドに対象のレコードIDを直接記述します
(そのため、事前に関連づけるレコードIDを知っておく必要があります)
上記の場合、 "group" というフィールドにレコードIDを設定しており、これで Person クラスと Group クラスの各レコードが関連付けられることとなります

下記コマンドで Person クラスに6レコード登録されたことが確認できます
> browse class Person
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |Skywalker           |25:0                
  1|    24:1|Han                 |Solo                |25:0                
  2|    24:2|Chewbacca           |null                |25:0                
  3|    24:3|Leia                |Organa              |25:0                
  4|    24:4|Darth Sidious       |null                |25:1                
  5|    24:5|Darth Vader         |null                |25:1                
---+--------+--------------------+--------------------+--------------------
関連付けられたレコードに対しては、「フィールド名.対象レコードのフィールド名」の形式で指定することで値を参照することができます
以下は select 文にて group フィールドに関連付けられた、 Group クラスの name フィールドを参照しています
(where 句にある "@rid" はレコードIDを意味するレコード属性になります)
> select name, surname, group.name from Person where @rid = 24:0
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|   -1:-1|Luke                |Skywalker           |Rebel Alliance      
---+--------+--------------------+--------------------+--------------------
また、他のフィールドと同様に where 句の検索条件としても使用できます
> select from Person where group.name = 'Rebel Alliance'
---+--------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |Skywalker           |25:0                
  1|    24:1|Han                 |Solo                |25:0                
  2|    24:2|Chewbacca           |null                |25:0                
  3|    24:3|Leia                |Organa              |25:0                
---+--------+--------------------+--------------------+--------------------
Java API を利用する場合、参照型レコードの登録は以下のようになります
(import 文、パッケージ名は省略しますのでご注意下さい)
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        // 新規レコード(Group)の作成
        ODocument jediOrder = new ODocument(database, "Group");
        jediOrder.field("name", "Jedi Order");
        jediOrder.save();

        // ユニークIDを取得
        ORID jediOrderORID = jediOrder.getIdentity();
        
        // 新規レコード(Rank)の作成
        ODocument master = new ODocument(database, "Rank");
        master.field("name", "Jedi Master");
        master.save();

        // ユニークIDを取得
        ORID masterOrderORID = master.getIdentity();

        ODocument knight = new ODocument(database, "Rank");
        knight.field("name", "Jedi Knight");
        knight.save();

        // ユニークIDを取得
        ORID knightOrderORID = knight.getIdentity();

        ODocument padawan = new ODocument(database, "Rank");
        padawan.field("name", "Padawan");
        padawan.save();

        // ユニークIDを取得
        ORID padawanOrderORID = padawan.getIdentity();

        // 新規レコード(Person)の作成
        ODocument yoda = new ODocument(database, "Person");
        yoda.field("name", "Yoda");
        yoda.field("group", jediOrderORID);
        yoda.field("rank", masterOrderORID);
        yoda.save();
        
        ODocument obiwan = new ODocument(database, "Person");
        obiwan.field("name", "Obi-Wan");
        obiwan.field("surname", "Kenobi");
        obiwan.field("group", jediOrderORID);
        obiwan.field("rank", knightOrderORID);
        obiwan.save();

        ODocument ahsoka = new ODocument(database, "Person");
        ahsoka.field("name", "Ahsoka");
        ahsoka.field("surname", "Tano");
        ahsoka.field("group", jediOrderORID);
        ahsoka.field("rank", padawanOrderORID);
        ahsoka.save();
        
        // 接続の解除
        database.close();
    }
}
上記では Group クラスに1レコード登録、Rank クラスの新規作成と3レコード登録、 Person クラスに3レコード登録しています
参照型の関連付けを行う方法はクエリを使用したケースと同様にフィールドにレコードIDを設定します
Java API にてレコードID( Java API では ORID クラスにて表現されています)を取得するには、ODocument クラスの getIdentity() メソッドを使用します
なお、新規レコードの場合、事前に save() メソッドを呼び出してデータベースに登録が完了していないとレコードIDは取得できませんので、ご注意ください

レコードを取得する場合は下記のようになります
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        System.out.println("-----レコードIDを指定してレコードを取得-----");
        
        // RID=24:6(Yoda) を取得
        ODocument yoda = new ODocument(database, new ORecordId(24, 6));
        
        // group フィールドを取得
        ODocument yodaGroup = yoda.field("group");
        Object yodaGroupName = yodaGroup == null ? "" : yodaGroup.field("name");
        // rank 1フィールドを取得
        ODocument yodaRank = yoda.field("rank");
        Object yodaRankName = yodaRank == null ? "" : yodaRank.field("name");
        
        // 取得レコードの出力
        System.out.println("name   : " + yoda.field("name"));
        System.out.println("surname: " + yoda.field("surname"));
        System.out.println("group  : " + yodaGroupName);
        System.out.println("rank   : " + yodaRankName);
        System.out.println();

        System.out.println("-----クエリを実行してレコードを取得-----");
        
        // SELECT 文を作成する
        String selectQuery = "select from Person where group.name = 'Jedi Order' ";

        // クエリを実行する
        List<ODocument> people = database.query(new OSQLSynchQuery<ODocument>(selectQuery));

        for (ODocument person : people) {
            // group フィールドを取得
            ODocument group = person.field("group");
            Object groupName = group == null ? "" : group.field("name");
            // rank 1フィールドを取得
            ODocument rank = person.field("rank");
            Object rankName = rank == null ? "" : rank.field("name");

            // 取得レコードの出力
            System.out.println("name   : " + person.field("name"));
            System.out.println("surname: " + person.field("surname"));
            System.out.println("group  : " + groupName);
            System.out.println("rank   : " + rankName);
            System.out.println();
        }

        // 接続の解除
        database.close();
    }
}
上記を実行すると、以下のように値が取得できます
-----レコードIDを指定してレコードを取得-----
name   : Yoda
surname: null
group  : Jedi Order
rank   : Jedi Master

-----クエリを実行してレコードを取得-----
name   : Yoda
surname: null
group  : Jedi Order
rank   : Jedi Master

name   : Obi-Wan
surname: Kenobi
group  : Jedi Order
rank   : Jedi Knight

name   : Ahsoka
surname: Tano
group  : Jedi Order
rank   : Padawan

次に組込型の関連付けですが、現在(2011年4月12日時点)のバージョンではクエリによる組込型のレコードの登録、更新(参照は可能です)は対応しておらず、 Java API でのみとなります

Java API を利用する場合の登録は以下のようになります
public class Main {

    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // 新規レコードを作成
        ODocument lightsaber = new ODocument(database, "Weapon");
        lightsaber.field("name", "Lightsaber");
        lightsaber.field("type", "sword"); 
        
        // RID=24:0(Luke) を取得
        ODocument luke = new ODocument(database, new ORecordId(24, 0));
        luke.field("weapon", lightsaber, OType.EMBEDDED);
        luke.save();
        
        database.close();
    }
}
上記では Weapon クラスのレコードを1件作成し、 Person クラスのレコードの "weapon" フィールドに設定しています
参照型と大きく異なる点は作成した Weapon クラスの save()メソッドを呼び出していない点、取得した Person クラスの "weapon" フィールドに設定する際、第3引数に "OType.EMBEDDED" を設定している点です

レコードの参照方法に関しては、組込型も参照型も差異はありません
>  select from Person where @rid = 24:0                          

---+--------+--------------------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |WEAPON              |SURNAME             |GROUP               
---+--------+--------------------+--------------------+--------------------+--------------------
  0|    24:0|Luke                |-1:-1               |Skywalker           |25:0                
---+--------+--------------------+--------------------+--------------------+--------------------
参照型のフィールド "group" にはレコードIDの値("25:0")が設定されているのに対し、組込型は直接レコードが設定されているため、レコードIDは設定されていません
組込まれたレコードのフィールドも同様の形式で参照可能です
> select name, surname, weapon.name, weapon.type from Person where @rid = 24:0

---+--------+--------------------+--------------------+--------------------+--------------------
  #| REC ID |NAME                |WEAPON              |SURNAME             |WEAPON2             
---+--------+--------------------+--------------------+--------------------+--------------------
  0|   -1:-1|Luke                |Lightsaber          |Skywalker           |sword               
---+--------+--------------------+--------------------+--------------------+--------------------
以上が OrientDB の関連付けの機能の紹介と利用方法になります

次回は、 OrientDB のグラフデータベースとしての機能を紹介したいと思います
(次はあまり期間をあけないようしたいと思います…)

2011年4月9日土曜日

NetBeans IDE 7.0 RC 2 リリース

NetBeans IDE 7.0 RC2 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


リリース予定が延びて、(4月9日現時点では)4月中予定というざっくりとした感じになったみたいです
何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年3月30日水曜日

NetBeans IDE 7.0 RC 1 リリース

NetBeans IDE 7.0 RC1 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです


既に3月も終わろうとしていますが、本日(2011年3月30日)時点では4月4日の正式リリース予定に変更はないようです
何かお気づきの点などありましたら、 ML 等へご連絡頂ければと思います

2011年3月9日水曜日

Mac OS X に Erlang をインストールする

Mac OS X に Erlang をインストールする方法の紹介です

Windows 環境の場合では、公式ページにてバイナリが配布されていますが、Mac用はありません
そのため、ソースからビルドする必要がありますが、 Homebrew などのパッケージ管理ツールを入れていると簡単に導入することができます
Homebrew を使用した Erlang のインストール方法は以下の通りです
(インストール前にパッケージリストを最新にすることをおすすめします)

$ brew install erlang

上記コマンド実行後、github から最新のソースコードを取得し、ビルドします
(2011年03月09日時点での最新バージョンは R14B01 です)
ビルド完了後、下記コマンドを実行して、バージョン情報が表示されれば、インストールは完了です

$ erl -version
Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 5.8.2

2011年2月20日日曜日

NetBeans IDE 7.0 Beta 2 リリース

NetBeans IDE 7.0 Beta2 がリリースされました
ダウンロードはコチラからできるようになっております

恒例のスプラッシュです

既にご存知の方も多いかと思いますが、ライセンスの関係で NetBeans と JUnit は(ライセンス問題が解決するまでは)同梱されて配布されなくなるようです
といっても、同梱されないだけで、ユーザ自身でライセンスに承認することで関連モジュールと一緒にダウンロード、インストールすることが可能となっており、インストール後は従来通りの機能が利用できます

まず、インストール直後の初回起動にて、下記のようなメッセージが表示されます
(現在は英語で表示されていますが、日本語化が進めば、日本語のメッセージが表示されると思います)

「了解」ボタンをクリックすることで、ダウンロードを開始します


ダウンロードが終了すると、インストール画面が表示されます

「次へ」ボタンをクリックすると、JUnit ライセンス承認となりますので、内容を確認後、承認する場合は「すべてのライセンス契約条件に同意する。」チェックボックスをチェックし、「インストール」ボタンをクリックします。

以降はウィザードの指示に従い、 NetBeans の再起動を行って終了です
Beta 2 では JUnit 4.8.2 を利用することができます

正式リリースまでにライセンス問題が解決するかは不明ですので、インストール後に上記のようなひと作業があることを念頭に入れておく必要がありそうです

また、Beta 2 では以前ご紹介させて頂いていた Git サポートがインストール可能となっています
アップデートセンターの登録など、特別な設定をしなくても「使用可能なプラグイン」として表示されます
※開発途中のプラグインですので、ご利用は自己責任でお願いします

Beta 2 以降は、3月にRCリリース、4月に正式リリース予定となっています
何かお気づきの点などありましたら、 ML へご連絡頂ければと思います

2010年11月17日水曜日

MacPorts から Homebrew へ移りました

HDD の乗せ換えで OS 丸ごとクリーンインストールしたことを契機に、長年お世話になった MacPorts から Homebrew に移ることにしました

MacPorts 自体は管理しているパッケージも豊富、動作も速く、申し分ないのですが、唯一不満なのは Mac に標準で入っている(MacPorts の管理外の)アプリケーションを考慮せずに、新たにインストールする点です
(例えば、 Mac にはデフォルトで perl 5.10 がインストールされていますが、 MacPorts でインストールするパッケージが perl に依存するものである場合、デフォルトのそれではなく、依存パッケージとして新規に perl をインストールしようとします)

ということで、その不満を解消してくれる Homebrew の導入に踏み切りました
※Homebrew も管理パッケージがまだまだ少ないなど、全く不満がないわけではないので、インストールされる際は、各々のメリット、デメリットを考慮の上、お試しください

インストール前に下記のような条件があります
(原文はココで、注釈は端折ってますので、気になる方は原文を参照下さい)

・CPU が Intel な Mac であること
・OS は 10.5 Leopard か、それ以上であること
・X11 込みの XCode
Java Developer Update

Java Developer Update は特に、Apple リリースの "1.6.0_22 JRE update" をインストール、使用している場合は必ずインストールすることをお勧めします(cmake 等のインストールでコケます)
Apple Developer から最新の Developer Package (2010年11月17日時点では "Java for Mac OS X 10.6 Update 3 Developer Package") をダウンロードし、インストールして下さい
また、上記公式の注釈には(言うまでもないからか)記述がないのですが、インターネットへの接続が必要です

以上の条件が満たせたら、実際に Homebrew をインストールしてみます
インストールは至って簡単で、下記コマンドで完了します
※インストール中、管理者( sudo )のパスワードを求められるので、入力してください

$ ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"

Homebrew は "/usr/local" 以下に自身とパッケージをインストールするので、 PATH を通します
".bash_profile" など適当なファイルに下記を記述してください

export PATH=/usr/local/sbin:/usr/local/bin:$PATH

PATH を反映後、 "brew -v " コマンドを実行し、インストールが正常に行われているかを確認します
下記のようにバージョン番号が表示されたら正常に完了しています
(2010年11月17日時点では最新バージョンは 0.7.1 です)

$ brew -v
0.7.1

次に、パッケージ( homebrew では fomula と呼んでいますが、今回はパッケージで表記を統一させていただきます)のインストールを行います
下記コマンドにてパッケージのインストールを行います

$ brew install [インストールしたいパッケージ名]

"cmake" をインストールしたい場合は、下記のようになります

$ brew install cmake

対応しているパッケージを検索する場合は下記のとおりです

$ brew search [検索したいパッケージ名(の一部)]

"make" という名前が含まれるパッケージを検索したい場合は、下記のようになります
(実行結果も併せて記載します)

$ brew search make
cmake colormake makensis o-make premake smake

Homebrew 自身(と管理パッケージ情報)の更新は下記のようになります

$ brew update

インストール済みのパッケージが(管理パッケージにて)最新版かどうかの確認は下記のコマンドを使用します

$ brew outdated

アップグレードする際は、インストールと同様に "brew install [パッケージ名]" コマンドで可能です
※古いパッケージを一括でアップグレードする方法をご存知の方がいましたら、コメントいただけると助かります

以上、簡単ですが、 Homebrew の使い方になります
自分でパッケージを作るのも簡単なようなので、機会があれば挑戦したいと思います

2010年9月22日水曜日

オープンソース NoSQL データベース OrientDB を使ってみる #2

前回に引き続き、 OrientDB の紹介です
今回は Java API を使用したデータの操作について紹介します
OrientDB では使用する API によりドキュメント指向データベース、オブジェクトデータベース、グラフデータベースとしての特性を利用することができます
(実際はドキュメント指向データベースをベースに、各データベースの特性のラップを通して利用するという実装です)
以降の説明では基本となるドキュメント指向データベースとしての操作について説明しています

操作の対象は、今回もサーバーとして起動している OrientDB とします
OrientDB のインストール、設定、起動については下記のエントリを参照ください

オープンソース NoSQL データベース OrientDB を使ってみる #1

使用する環境は以下のとおりです

・Mac OS X 10.6.4
・Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065)
・OrientDB 0.9.22
・NetBeans 6.9.1
※以降の説明はお使いの環境に合わせて、適時読み替えてください

まず、 NetBeans にて Java アプリケーションの新規プロジェクトを作成します
プロジェクト名は任意で構いませんが、ここでは説明のため "OrientDBSample" とします
「主クラスを作成」チェックボックスもチェックしていて下さい

プロジェクト作成後、必要なライブラリの追加を行ないます
"OrientDBSample" プロジェクト内の「ライブラリ」フォルダを右クリックし、表示されたコンテキストメニューより「JAR/フォルダを追加...」をクリックします

ファイル選択ダイアログが表示されるので、 OrientDB を展開したフォルダ内の "lib" フォルダにある、 "orientdb-client-0.9.22.jar" 、及び "orientdb-core-0.9.22.jar" を選択し、「選択」ボタンをクリックします
ダイアログが閉じると、「ライブラリ」フォルダ内に上記2つの JAR ファイルが追加されていることが確認できるかと思います

まず、データベースへ接続を行ないます
接続は前回同様 demo データベースを使用します
プロジェクト作成時に自動生成された Main クラスの main メソッド内に以下のようにコードを追加します
(「主クラスを作成」オプションを選択していなかった場合は、 main メソッドをもつ適当なクラスを作成してください)
package orientdbsample;

import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;

public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        // 接続の解除
        database.close();
    }
}
以降は上記のソースを基本に処理のコードを追加していきます
(import 文、パッケージ名は省略しますのでご注意下さい)

まずは、登録処理を行うコードです
入力後、正常に動作が完了することを確認してください
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // Rebellion クラスのレコードを作成
        // ※指定したクラスがデータベースに存在しない場合、自動的に作成してくれます
        ODocument document = new ODocument(database, "Rebellion");
        document.field("name", "Luke");
        document.field("surname", "Skywalker");
        document.save();

        // メソッドチェーンを利用して、 Rebellion クラスのレコードを作成
        new ODocument(database, "Rebellion").field("name", "Han").field("surname", "Solo").save();

        // 接続の解除
        database.close();
    }
}
ORientDB ではドキュメントは ODocument クラスを使用して表します
上記例では、 "Rebellion" クラスのドキュメントを作成しています
"Console" アプリケーションを使用した際には事前にクラスの作成が必要でしたが、 Java API を利用する際にはクラスが存在しない場合は自動的に作成してくれます
フィールドメソッドを使用し、指定したフィールド名にフィールド値を設定します
クラスに指定したフィールドが存在しない場合、新たに追加されます
フィールド値に指定可能な型は以下のようになっています

・文字列型 (java.lang.String)
・ Byte 型 (java.lang.Byte または byte)
・ Short 型 (java.lang.Short または short)
・ Integer 型 (java.lang.Integer または int)
・ Long 型 (java.lang.Long または long)
・ Float 型 (java.lang.Float または float)
・ Double 型 (java.lang.Double または double)
・ Boolean 型 (java.lang.Boolean または boolean)
・日付型 (java.util.Date)
・バイナリ (byte[])
・リスト型 (java.util.Set)
・セット型 (java.util.Set)
・マップ型 (java.util.Map)

上記に加えて、レコード間の関連を表す Link とそれに関係する型が OrientDB にてサポートされている型となります
( Link に関しては別エントリにて説明したいと思います)
例ではシンプルに文字列のみをフィールド値に設定しています
フィールドに値を設定した後、 save() メソッドでデータベースへの登録を行ないます

また、OrientDB ではデータ操作に対して( "Console" アプリケーションと同様に) SQLライクなクエリ(以降は SQL と記述します)を使用することができます
Java API を利用した SQL の実行は OSQLQuery クラスのサブクラス(下記例では OCommandSQL クラス)を使用します
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // INSERT 文を作成する
        String insertQuery = "insert into Rebellion (name) values ('Chewbacca')";

        // クエリを実行します
        database.command(new OCommandSQL(insertQuery)).execute();

        // 接続の解除
        database.close();
    }
}
次に browseClass メソッドを使用して、先ほど登録した Rebellion クラスの全レコードを表示します
("Console" アプリケーションの "browseClass" コマンドと同様の結果となります)
取得できたレコードの getIdentity() メソッドを呼びだすと、データベースにてユニークなキーとなる、レコード IDが取得できます
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // Rebellion クラスのレコードのリストを取得
        Iterable<ODocument> documents = database.browseClass("Rebellion");

        // レコードのリストから各レコードを取得します
        for (ODocument person : documents) {
            // レコードの各フィールドを取得
            // レコード ID を取得
            System.out.println("Rec ID : " + person.getIdentity());
            System.out.println("Name   : " + person.field("name"));
            System.out.println("Surname: " + person.field("surname"));
        }

        // 接続の解除
        database.close();
    }
}

実行後、以下のように出力されるかと思います
Rec ID : 19:0
Name : Luke
Surname: Skywalker
Rec ID : 19:1
Name : Han
Surname: Solo
Name : Chewbacca
Surname: null

クラスのレコード件数を取得するには countClass() メソッドを使用します
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // Rebellion クラスのレコード件数を取得します
        long count = database.countClass("Rebellion");

        System.out.println("Count: " + count);

        // 接続の解除
        database.close();
    }
}
また、個別のレコードを抽出するにはクエリを使用します
OrientDB では先の SQL とは別に Native クエリを使用することができますが、現在 Native クエリは local データベースに接続した場合のみ使用可能という制限があります
今回は remote データベースを前提としていますので、 Native クエリに関しては説明を省略します
Java API を利用したレコード抽出には OSQLQuery クラスのサブクラス(下記例では OSQLSynchQuery クラス)を使用します
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        // クエリ文字列を作成する
        // name フィールドのフィールド値が "L" で始まるもののみ抽出する
        String query = "select from Rebellion where name like 'L%' ";

        // クエリを実行し、結果のリストを取得します
        List<ODocument> documents = database.query(new OSQLSynchQuery<ODocument>(query));

        // レコードのリストから各レコードを取得します
        for (ODocument person : documents) {
            // レコードの各フィールドを取得
            // レコード ID を取得
            System.out.println("Rec ID : " + person.getIdentity());
            System.out.println("Name   : " + person.field("name"));
            System.out.println("Surname: " + person.field("surname"));
        }

        // 接続の解除
        database.close();
    }
}
実行後、以下のように出力されるかと思います

Rec ID : 19:0
Name : Luke
Surname: Skywalker

次にレコードの更新を行ないます
対象となるレコードを抽出し、値を更新後、 save() メソッドを実行して反映します
対象レコード抽出には "@rid" という特別なフィールド(属性値) とレコードIDを使用しています
また、INSERT 文と同様に command() メソッドと OCommandSQL クラスを使用して UPDATE 文を実行することができます
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");

        ODocument person = null;

        // SELECT 文を作成する
        String selectQuery = "select from Rebellion where @rid = 19:0";

        // クエリを実行し、その結果のリストを取得します
        person = ((List<ODocument>) database.query(new OSQLSynchQuery<ODocument>(selectQuery))).get(0);
        // レコードの各フィールドを取得
        System.out.println("Rec ID : " + person.getIdentity());
        System.out.println("Name   : " + person.field("name"));
        System.out.println("Surname: " + person.field("surname"));
        System.out.println("----------");

        // "name" フィールドのフィールド値を "" 更新する
        person.field("name", "Ben");
        person.save();

        // クエリを実行し、その結果のリストを取得します
        person = ((List<ODocument>) database.query(new OSQLSynchQuery<ODocument>(selectQuery))).get(0);
        // レコードの各フィールドを取得
        System.out.println("Rec ID : " + person.getIdentity());
        System.out.println("Name   : " + person.field("name"));
        System.out.println("Surname: " + person.field("surname"));
        System.out.println("----------");

        // UPDATE 文を作成する
        String updateQuery = "update Rebellion set name = 'Anakin' where @rid = 19:0";

        // クエリを実行します
        database.command(new OCommandSQL(updateQuery)).execute();

        // クエリを実行し、その結果のリストを取得します
        person = ((List<ODocument>) database.query(new OSQLSynchQuery<ODocument>(selectQuery))).get(0);
        // レコードの各フィールドを取得
        System.out.println("Rec ID : " + person.getIdentity());
        System.out.println("Name   : " + person.field("name"));
        System.out.println("Surname: " + person.field("surname"));
        System.out.println("----------");

        // 接続の解除
        database.close();
    }
}
実行後、以下のように出力されるかと思います

Rec ID : 19:0
Name : Luke
Surname: Skywalker
----------
Rec ID : 19:0
Name : Ben
Surname: Skywalker
----------
Rec ID : 19:0
Name : Anakin
Surname: Skywalker
----------

最後にレコードの削除を行ないます
対象となるレコードを抽出し、 delete() メソッドを実行して削除します
また、 command() メソッドと OCommandSQL クラスを使用して、 DELETE 文を実行することも可能です
public class Main {
    public static void main(String[] args) {
        // admin ユーザでサーバーの demo データベースに接続します
        ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
        
        // SELECT 文を作成する
        String selectQuery = "select from Rebellion where @rid = 19:0 ";

        // レコードのリストから各レコードを取得します
        for (ODocument document : database.browseClass("Rebellion")) {
            // レコードの各フィールドを取得
            System.out.println("Rec ID : " + document.getIdentity());
            System.out.println("Name   : " + document.field("name"));
            System.out.println("Surname: " + document.field("surname"));
        }

        System.out.println("----------");

        // クエリを実行し、その結果を取得します
        ODocument person = ((List<ODocument>) database.query(new OSQLSynchQuery<ODocument>(selectQuery))).get(0);
        // 取得したレコードの delete() メソッドを実行し、レコードを削除
        person.delete();

        // DELETE 文を作成する(全件削除)
        String deleteQuery = "delete from Rebellion";

        // クエリを実行します
        database.command(new OCommandSQL(deleteQuery)).execute();

        // Rebellion クラスの件数取得(レコード有無判定)
        if(database.countClass("Rebellion") > 0) {
            // レコードのリストから各レコードを取得します
            for (ODocument document : database.browseClass("Rebellion")) {
                // レコードの各フィールドを取得
                System.out.println("Rec ID : " + document.getIdentity());
                System.out.println("Name   : " + document.field("name"));
                System.out.println("Surname: " + document.field("surname"));
            }
        } else {
            System.out.println("Rebellion クラスにはレコードは存在しません");
        }

        // 接続の解除
        database.close();
    }
}
実行後、以下のように出力されるかと思います

Rec ID : 19:0
Name : Anakin
Surname: Skywalker
Rec ID : 19:1
Name : Han
Surname: Solo
Rec ID : 19:2
Name : Chewbacca
Surname: null
----------
Rebellion クラスにはレコードは存在しません

以上で、Java API を利用した OrientDB の操作方法になります
今回説明はしませんでしたが、 OrientDB にはトランザクションも利用できます
しかし、最新リリース版として使用している 0.9.22 ではバグがあり、正しく利用できないという状態です
開発版ではこの問題は修正されているので、次回リリース版である 0.9.23 (10月中旬リリース予定)では問題なく利用出来るかと思います

次回はデータ間の関連(リレーション)について紹介したいと思います

2010年9月17日金曜日

オープンソース NoSQL データベース OrientDB を使ってみる #1

今回は OrientDB という オープンソースの NoSQL データベースを紹介致します
※OrientDB は開発が活発なプロジェクトであるため、記載した機能等が将来変更される可能性があります
 (実際、このエントリ書いてる最中にバージョン上がるし、実行ファイル名変わるし…)

OrientDB は今年(2010年)5月に公開された、新しいプロダクトです
(なお、ベースとなった Orient ODBMS ( C++ にて実装) は1999年にリリースされており、これは10年近くの実績があります)
開発者は Luca Garulli というイタリアの方で、 JDO 1.0 、 2.0 のエキスパートメンバーのひとりです
現在のところ Luca 1人で開発していますが、将来的にはコミュニテイとして開発者を増やしたいとのことです
(そのため、 Wiki のドキュメント整備まで手が回らないのか、情報が最新版と一致していない箇所があります)

OrientDB は DBMS の分類では CouchDB や MongoDB と同じ、ドキュメント指向データベースですが、データ間の関連(リレーション)はグラフデータベースのように扱うといった、複数の DBMS の特徴を備えたものとなっています
この他にも OrientDB には以下のような特徴があります

・100% Java にて記述されている
・軽量である(本体のみで約1MB)
・高速である(一般的なコンピュータ(※1)にて200,000件/秒の登録が可能(※2))
・グラフデータベースのスタックとして Tinkerpop を採用
 (Gremlin などの対応プロダクトが利用可能)
・データ操作には、Java API 、HTTP Restful API、 SQL ライクな構文をサポート
・スキーマレス、スキーマフル、複合の複数のスキーマタイプを選択可能
・ACIDトランザクションのサポート
・組込モード、サーバーモードの2つの動作モードをサポート
・ライセンスは Apache License 2.0
※1 … DELL Notebook model XPS M1530 with Intel(r) Core Duo T7700 2.40Ghz, 3 GB RAM and HD 5.400rpm, O.S. MS Windows Vista, JRE 1.6.0_20
※2 … インメモリでの処理時

また、 OrientDB を基盤とした OrientKV というキー・バリューストアのプロダクトがあります
(OrientDB、OrientKV(Key/Value Server) とは別に Orient Object(Object Database) というプロダクトもあるのですが、 OrientDB のコア機能として含まれているようなのでここでの説明は割愛しています)
OrientKV は本体が軽量、データ処理が高速であるという OrientDB の良い部分を引き継ぎ、且つ複数ノードにデータを分散させて格納する、分散キー・バリューストアとしての運用が設定にて簡単に実現できるという特徴があります
OrientKV の詳細に関しては別エントリにてご紹介したいと思います

次に OrientDB のインストールと、実際の動作についてです
以下の説明は下記環境にて行っています
Windows、Linux をご利用の方は、各環境に合わせて読み替えていただければと思います
(Windows 環境では .sh ファイルを .bat ファイルと読み替えるなど)

・Mac OS X 10.6.4
・Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065)

OrientDB のインストールはパッケージのダウンロード、及び展開のみで完了します
コチラのリストより最新版(2010年09月17日現在)である "orientdb-0.9.22.zip" をダウンロードし、適当な場所に展開します

展開後、 "config" ディレクトリ内にある "orient-server-config.xml" ファイルを開き、9行目、10行目ほどにあるリスナのポート番号をご使用の環境に合わせ、変更します
(デフォルト値として設定されている、"2424-2430"(9行目)、"2480-2490"(10行目)の範囲内のポート番号が使用可であれば、特に変更は必要ありません)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<orient-server>
<network>
<protocols>
<protocol implementation="com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary" name="binary"/>
<protocol implementation="com.orientechnologies.orient.server.network.protocol.http.ONetworkProtocolHttpDb" name="http"/>
</protocols>
<listeners>
<listener protocol="binary" port-range="2424-2430" ip-address="127.0.0.1"/>
<listener protocol="http" port-range="2480-2490" ip-address="127.0.0.1">
<!-- 〜中略〜 -->
</orient-server>

また、 "bin" ディレクトリ内に移動し、下記ファイルに実行権限を付与します

$ cd ./bin
$ chmod +x ./server.sh ./console.sh

以上でインストール、及び初期設定は完了です

("bin" ディレクトリ内に移動したままの状態で)下記コマンドを実行し、サーバの起動を行ないます
(サーバを停止する場合は Ctrl + C にて停止します)

$ ./server.sh

最後に実際にデータの登録、参照、更新、削除を行ないたいと思います
OrientDB のデータに対しては、 Java API 、REST API 、同梱のクライアントアプリケーションの "Console" 、そして Web ベースのクライアントアプリケーションである "OrientDB Studio" から操作可能となっています
上記の中ではJava API の動作が一番安定していますが、使いやすさから今回は "Console" での操作を紹介します
(Java API での動作は次回紹介したいと思います)
なお、 "OrientDB Studio" はバグや未実装の機能が多く、 orientdb-0.9.22 のバージョンでは実用するには厳しい状態です

("bin" ディレクトリ内に移動したままの状態で)下記コマンドを実行し、"Console" の起動を行ないます
(起動後はプロンプトの入力待ち状態が ">" となります)

$ ./console.sh

起動後、まず "help" と入力します
下記のように各コマンドとその説明が表示されます

> help

AVAILABLE COMMANDS:

* get Return the value of a property
* classes Display all the configured classes
* set Change the value of a property
* delete Delete records from the database
* insert Insert a new record into the database
* connect Connect to a database
* update Update records in the database
* info Display information about current status
* properties Return all the configured properties
* disconnect Disconnect from the current database
* create database Create a new database
* create cluster Create a new cluster in the current database. The cluster can be physical or logical.
* remove cluster Remove a cluster in the current database. The cluster can be physical or logical.
* load record Load a record in memory and set it as the current one
* display record Display current record's attributes
* grant Grant privileges to a role
* revoke Revoke privileges to a role
* create link Create a link from a JOIN
* create class Create a class
* create property Create a property
* select Execute a query against the database and display the results
* script Execute a script against the current database. If the database is remote, then the script will be executed remotely.
* create index Create an index on a property
* create index Create an index on a property
* browse class Browse all the records of a class
* browse cluster Browse all the records of a cluster
* clusters Display all the configured clusters
* dictionary keys Display all the keys in the database dictionary
* dictionary get Loookup for a record using the dictionary. If found set it as the current record
* dictionary put Insert or modify an entry in the database dictionary. The entry is composed by key=String, value=record-id
* dictionary remove Remove the association in the dictionary
* export database Export a database
* compare databases Compare two databases
* import database Import a database into the current one
* export record Export the current record in the requested format
* help Print this help
* exit Close the console

コマンドの最後にある通り、 "exit" コマンドを使用すると、"Console" アプリケーションを終了することができます

次に "connect" コマンドを実行し、データベースに接続します
"connect" コマンドは以下のように入力します

connect <接続モード>:<データベースパス> <ユーザー名> <ユーザーパスワード>
・"接続モード" には "local" と "remote" があり、ローカルデータベースへの接続は "local" 、ローカル、またはリモートにて起動しているサーバーへの接続には "remote" を使用してください
・"データベースパス" はデータベースまでのパスとなります
 接続モードによりパスの指定が異なり、 "local" ではデータベースまでのファイルパス、 "remote" ではサーバーのアドレスとデータベース名となります
・"ユーザー名" 、 "ユーザーパスワード" はデータベースに設定されているユーザー名、パスワードとなります
 データベース作成時、デフォルトで下記ユーザーが作成されます

  ・ユーザー名:admin / パスワード : admin … データベースに対して、書き込み、読み込み権限を持ちます
  ・ユーザー名:writer / パスワード : writer … データベースに対して、書き込み限を持ちます
  ・ユーザー名:reader / パスワード : reader … データベースに対して、読み込み権限を持ちます

今回はユーザーは "admin" 、データベースは、デフォルトで作成されている "demo" データベースを利用します
使用するコマンドは下記のようになります

> connect remote:localhost/demo admin admin

"Connecting to database [remote:localhost/demo] with user 'admin'...OK" と表示され、入力待ち状態となったら接続成功です
接続に失敗する場合は、ポート番号が衝突していないか、確認してみてください

次にデータを登録しますが、その前にまずクラスの作成を行う必要があります
クラスは RDBMS の表と似た概念になり、データ集合のモデルとなるものです
なお、 OrientDB のクラスは、(上記特徴にも書いたとおり)スキーマレス、スキーマフル、両者の混在という設定が可能です
クラスの作成には "create class" コマンドを使います
"create class" コマンドは以下のように入力します

create class <クラス名>
・"クラス名" は作成するクラス名を指定します
 (クラスの識別として大文字小文字は区別されます)

使用するコマンドは下記のようになります

> create class Person

"Class created successfully with id=xx"(xx はユニークな ID、データベース上にあるクラスの ID が表示されます) と表示されれば、クラスの作成は完了です。
ここで、大きなバグがあるのですが、クラスを作成しても即時反映がされません
"exit" コマンドで接続解除をして、 "console.sh" でコンソールを再起動し、 "connect" コマンドで接続しなおしてください
再接続後、"classes" コマンドを実行すると、既存のクラスに加えて、先程作成したクラス名が表示されるのがわかります

> classes
CLASSES:
--------------------+------+------------------------------------------+-----------+
NAME    | ID | CLUSTERS         | ELEMENTS |
--------------------+------+------------------------------------------+-----------+
ORole    |  0| orole         |   3 |
OUser    |  1| ouser         |   3 |
Account    |  2| account         |  1005 |
Company    |  3| company         |   9 |
Profile    |  4| profile         |   9 |
Whiz    |  5| whiz          |  1000 |
Address    |  6| address         |  164 |
City    |  7| city          |  55 |
Country    |  8| country         |  55 |
Animal    |  9| animal         |   0 |
AnimalRace   | 10| animalrace        |   3 |
OGraphVertex  | 11| ographvertex        |  102 |
OGraphEdge   | 12| ographedge        |  101 |
Person    | 13| person         |   0 |
--------------------+------+------------------------------------------+-----------+
TOTAL                  2509 |
----------------------------------------------------------------------------------+

作成したクラスにスキーマを定義することが可能ですが、今回はスキーマレスで使用します

OrientDB ではデータ操作に、 RDBMS のように SQL に似た構文を使用することができます
データの登録には "INSERT" 文を使います

INSERT INTO <クラス名>|cluster:<クラスタ名> (<フィールド名>[,]*) VALUES (<フィールド値>[,]*)
・"クラス名"にはデータを登録するクラスの名前を記述します
・"クラスタ名" にはデータを格納するクラスタ名を記述します
 (クラスタは今回使用しませんので、説明は省略します)
・"フィールド名"をキーに"フィールド値"が登録されます

以下のデータを登録してみます

> insert into Person (name, surname) values ('Marty', 'McFly')

実行後、 "Inserted record Person@19:0{name:Marty,surname:McFly} in X sec(s)."(Xは秒数(環境により異なります)) のように表示されたら登録成功です
登録されたデータを確認する簡単な方法は "browse class" コマンドを使用することです

> browse class Person

---+--------+--------------------+--------------------
#| REC ID |NAME    |SURNAME   
---+--------+--------------------+--------------------
0| 19:0|Marty    |McFly   
---+--------+--------------------+--------------------

また、 SQL のように "SELECT" 文を使用することもできます
("browse class" コマンドと異なり、抽出する条件や並び順などを指定できます)

SELECT FROM <対象> [WHERE <条件>*] [ORDER BY <フィールド名>* [ASC|DESC]*]
・"対象"には検索する"クラス名"、"クラスタ名"、及び"レコードID"が指定可能です
 ("クラスタ名"、"レコードID"については今回使用しませんので、説明は省略します)
・"条件"には、データを抽出する条件を指定します(省略可能です)
・ORDER BY 句を使用した場合、指定した "フィールド名" 順に昇順( "ASC" )、降順( "DESC" )に並べ替えます

先程登録したデータを検索します

> select from Person where name = 'Marty' order by surname

---+--------+--------------------+--------------------
#| REC ID |NAME    |SURNAME   
---+--------+--------------------+--------------------
0| 19:0|Marty    |McFly   
---+--------+--------------------+--------------------

次はデータの変更(更新)を行ないます

update <クラス名>|cluster:<クラスタ名> set [[,] <フィールド名> = <フィールド値>]* [where <条件>]
・"クラス名"にはデータを更新するクラスの名前を記述します
・"クラスタ名" には更新するデータが格納されたクラスタ名を記述します
 (クラスタは今回使用しませんので、説明は省略します)
・"フィールド名"の値を"フィールド値"にて更新します
・"条件"には、更新対象となるデータの条件を指定します(省略可能ですが、対象が全件となります)

登録したデータを更新します

> update Person set name = 'George' where name = 'Marty'

実行後、 "Updated 1 record(s) in X sec(s)." (Xは秒数(環境により異なります))のように表示されたら更新成功です
"browse class" コマンドを使用すると、変更が確認できます

> browse class Person

---+--------+--------------------+--------------------
#| REC ID |NAME    |SURNAME   
---+--------+--------------------+--------------------
0| 19:0|George    |McFly   
---+--------+--------------------+--------------------

最後にデータの削除を行ないます

DELETE FROM <クラス>|cluster:<クラスタ> [WHERE <条件>]
・"クラス名"にはデータを削除するクラスの名前を記述します
・"クラスタ名" には削除するデータが格納されたクラスタ名を記述します
 (クラスタは今回使用しませんので、説明は省略します)
・"条件"には、削除対象となるデータの条件を指定します(省略可能ですが、対象が全件となります)

更新したデータを削除します

> delete from Person where surname = 'McFly'

実行後、 "Delete 1 record(s) in X sec(s)."(Xは秒数(環境により異なります)) のように表示されたら削除成功です
"browse class" コマンドを使用すると、データが存在しないことが確認できます

> browse class Person

以上で、"Console" アプリケーションを使用した OrientDB の操作方法になります
次回は、 Java API を利用した OrientDB の操作方法を紹介したいと思います