11
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Play Framework(v2.2.3)からMongoDBを使う

Last updated at Posted at 2014-05-18

Play初心者がMongoDBを使えるようになるまでのメモ。

環境

Mac OS X - 10.9.2
play(java) - 2.2.3
MongoDB - 2.6.1
Eclipse - 4.3.2

ソースコード

Morphia

https://github.com/mongodb/morphia
"Morphia is a lightweight type-safe library for mapping Java objects to/from MongoDB."
どうやらこれを使えばよさそうなのでこれを使うことにします。

play-morphia

http://www.playframework.com/modules/morphia
playへmorphiaを組み込むための公式っぽいモジュールがあったっぽいですが
適用可能なplayのバージョンが1.xのみ、ということで使えません。

playMongoDemo

公式ドキュメントにMongoDB関連のドキュメントがあんまり無い気がしたので適当に検索してたら
https://github.com/czihong/playMongoDemo
playでしかもmorphiaを使っているデモを見つけられたのでcloneしてplayしようとしたら色々エラーが出て動きませんでした。
どうやらplay自体のバージョンが異なる事が原因でした。
"play migration"とかで検索するとなんだかバージョン間の移行に関するページが沢山出てきて、とりあえずそれに従って進めていましたがうまく行かないため挫折。
2.0, 2.1, 2.2でかなり変わっているようですね。playバージョン管理ツールが欲しくなりましたが存在してませんよね?

play new myapp

というわけでplayMongoDemoを参考にしつつ、自分で手探りで作っていくことにしました。

Global.java

playMongoDemoにあったのものをまるまるコピーします。
GlobalSettingsオブジェクトでアプリケーションの起動時にMongoDBに接続しているっぽいですね。
GlobalSettings

Global.java
import java.net.UnknownHostException;

import com.google.code.morphia.Morphia;
import com.mongodb.Mongo;

import controllers.MorphiaObject;
import play.GlobalSettings;
import play.Logger;

public class Global extends GlobalSettings {
  @Override
  public void onStart(play.Application arg0) {
    super.beforeStart(arg0);
    Logger.debug("** onStart **"); 
    try {
      MorphiaObject.mongo = new Mongo("127.0.0.1", 27017);
    } catch (UnknownHostException e) {
      e.printStackTrace();
    }
    MorphiaObject.morphia = new Morphia();
    MorphiaObject.datastore = MorphiaObject.morphia.createDatastore(MorphiaObject.mongo, "test");
    MorphiaObject.datastore.ensureIndexes();   
    MorphiaObject.datastore.ensureCaps();  

    Logger.debug("** Morphia datastore: " + MorphiaObject.datastore.getDB());
  }
}

Global.javaで使われているMorphiaObjectもplayMongoDemoで以下のように定義されてるのでコピー。

MorphiaObject.java
package controllers;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.mongodb.Mongo;

public class MorphiaObject {
  static public Mongo mongo;
  static public Morphia morphia;
  static public Datastore datastore;
}

build.sbt

import文で使われてる"com.google.code.morphia"とか"com.mongodb.Mongo"とかを使うためには、build.sbtに色々追記する必要があります。

libraryDependencies ++= Seq(
  javaJdbc,
  javaEbean,
  cache,
  "com.google.code.morphia" % "morphia" % "0.99",
  "org.mongodb" % "mongo-java-driver" % "2.7.3",
  "de.flapdoodle.embed" % "de.flapdoodle.embed.mongo" % "1.36" % "test"
)

libraryDependenciesに追記します。
デフォルトだとjavaJdbc,javaEbean,cacheのみが書かれていますが、以下の3個を追加します。一番下のやつはテストを書く時に使います。
その後、追加したライブラリを.classpathとかに反映させるためにplayコンソールに入って
eclipse with-source=trueとかしたりします。うまく行かない時はplay cleanしてもう一度やったりして、今のところはうまく行きました。

モデル

https://github.com/brly/play-morphia-sample/blob/master/app/models/TestModel.java
playMongoDemoに沿って定義します。このソース例ではメンバ数を減らして、

{
  name: String,
  value: Int
}

こんな感じの簡単なやつです。
あとソースを見れば分かりますがRequiredアノテーションとかも使えます。

コントローラとルーティング

https://github.com/brly/play-morphia-sample/blob/master/conf/routes
https://github.com/brly/play-morphia-sample/blob/master/app/controllers/Application.java
playMongoDemoに沿って変更。play.data.Formあたりの仕様が変わってるので調整する。

ビュー

https://github.com/brly/play-morphia-sample/blob/master/app/views/index.scala.html
これはplayMongoDemoのままでも大丈夫だったような気がします。

実行

スクリーンショット 2014-05-18 18.39.58.png
5個程要素を追加後の画面です。

テスト

テストを書かないと色々言われるご時世なので書かないといけませんが、環境を整えなければなりません。
MySQLの場合だとplayのfakeApplicationとかinMemoryDatabaseを使えば良かったのですが、それは使えないので用意する必要があります。

という訳でまたぐぐったところ、以下の記事を見つけます。
http://www.cubeia.com/2012/03/using-mongodb-for-your-game-data/
見慣れたMorphiaという単語が安心感を与えてくれますが、新たな"EmbedMongo"という単語が出てきます。

EmbedMongo

というわけで"embedded mongo unit test"とかで検索するといかにもなページがあります。
http://quillbytes.com/display/JAVA/Setting+Up+An+Embedded+MongoDB+Database+for+Unit+Tests
でサンプル例があるのですが、サンプルのテストが書きたい感じとちょっと違います。
例ではDBCollectionとかいうオブジェクトを使ってread/writeをしてます。
TestModel.javaではそんな感じに書いてなかったので、どうしたら良いのかよくわかりませんでしたがとりあえず以下のようにしたらfakeぽく動作するようになりました。

TestModelTest.java
@Before
  public void beforeTest() {
    MorphiaObject.mongo = getMongoClient();
    MorphiaObject.datastore = new Morphia().createDatastore(getMongoClient(), "test");
  }

@Beforeで毎回MorphiaObjectのmongoとdatastoreを初期化して書きたかった感じにテストを書きます。

TestModelTest.java
 @Test
  public void 初期値は空リスト() {
    assertThat(TestModel.all()).isEmpty();
  }
  
  @Test
  public void addしたものが順番に取り出せる() {
    TestModel ts0 = new TestModel();
    ts0.name = "ほとココア";
    ts0.value = 15;
    TestModel.create(ts0);
    
    TestModel ts1 = new TestModel();
    ts1.name = "かふうチノ";
    ts1.value = 13;
    TestModel.create(ts1);
    
    TestModel ts2 = new TestModel();
    ts2.name = "てでざリゼ";
    ts2.value = 16;
    TestModel.create(ts2);
    
    TestModel ts3 = new TestModel();
    ts3.name = "うじまつチヤ";
    ts3.value = 15;
    TestModel.create(ts3);
    
    TestModel ts4 = new TestModel();
    ts4.name = "きりまシャロ";
    ts4.value = 15;
    TestModel.create(ts4);
    
    assertThat(TestModel.all()).hasSize(5);
    assertThat(TestModel.all().get(0).name).isEqualTo("ほとココア");
    assertThat(TestModel.all().get(1).name).isEqualTo("かふうチノ");
    assertThat(TestModel.all().get(2).name).isEqualTo("てでざリゼ");
    assertThat(TestModel.all().get(3).name).isEqualTo("うじまつチヤ");
    assertThat(TestModel.all().get(4).name).isEqualTo("きりまシャロ");
  }

という訳で、なんとか環境が出来ました。

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?