【入門編】Slim3で始める!GAE/JでWebアプリケーション開発 (第1回)

アプリケーションの開発

早速、SimpleBBSアプリケーションの開発を始めましょう。

今回はModelおよびServiceから作成していきます。データストアの使い方さえ覚えてしまえば、あとは普通のJavaのWebアプリケーション開発と同じです。

Modelの作成

SimpleBBSの肝となる記事のデータオブジェクトであるModelクラスを設計します。構成は以下のようなイメージです。

作成するModelの構成

作成するModelの構成

記事情報全体をを表すHead、記事本文のBody、記事に対するCommentの3クラスを作成します。

記事情報(Head)からあえて記事本文を抜き出し別クラスとした理由は、SimpleBBSの画面構成上、<トップ>の記事一覧では見出しのみを表示し、記事本文は表示しないためです。記事本文はデータサイズが大きくなりうるので、無駄にメモリを食わないよう考慮しました。

作成手順

Model作成の流れは以下の通りです。

  1. Antタスク gen-model にてModelクラスの雛形を作成
  2. 必要なプロパティ(とアクセッサ)の追加
  3. 必要なリレーションシップの追加

では、実際の手順を説明します。

  • プロジェクト直下のbuild.xmlのAntタスクから gen-model を実行します。
    gen-modelの実行イメージ
    【補足】Antビューに何も表示されていない場合は、 build.xml をAntビューに追加して下さい。build.xmlをAntビューにドラッグ&ドロップイメージ
  • Model名を入力するプロンプトが表示されるので、ルートパッケージから見た相対パスのクラス名を入力しOKボタンを押します。Model名の入力プロンプトイメージすると、antタスクによりModelの雛形が自動生成されます。
    Modelの雛形が作成されたイメージ
    Slim3のModelクラスは、以下の2つの条件を満たす必要があります。

    • クラスのアノテーションとして「@Model」をつける
    • 主キーとなるKeyプロパティが必要で、これに対し@Attribute(primaryKey=true)のアノテーションをつける

    gen-model を使うと、自動的にModelに必要なものが記述された状態で作成されます。

    また、LongのversionプロパティはSlim3が提供する楽観的排他制御に使います。必須ではありませんがそのまま定義しておきましょう。

    同様にBodyクラスとCommentクラスもgen-modelで生成して下さい。

  • 自動生成されたModelクラスに必要なプロパティ、リレーションシップを追加します。青字が追加したコードになります。

    Head.java

    package simplebbs.model.bbs;
    
    ~ import省略 ~ 
    
    @Model(schemaVersion = 1)
    public class Head implements Serializable {
    
    ~ key、versionプロパティ省略 ~ 
     
        // 記事見出し 
        private String subject;
        // 投稿日時 
        private Date postDate;
        // 投稿者名 
        private String username;
        // 編集用パスワード 
        private String password;
        // 最新コメントID(=コメント数) 
        private Long lastCommentId = 0L;
        // 最新コメント日時 
        private Date lastCommentDate;
    
        // Bodyへの1対1の関連 
        private ModelRef<Body> bodyRef = new ModelRef<Body>(Body.class);
        // Commentへの1対多の関連 
        @Attribute(persistent=false)
        private InverseModelListRef<Comment, Head> commentRef =
            new InverseModelListRef<Comment, Head>(Comment.class, CommentMeta.get().headRef, this);
     
    ~ アクセッサ以降省略 ~ 
    
    }

    上記では省略していますが、プロパティのアクセッサ(getter/setter)も忘れずに追加して下さい。

    また、今回は横着して出来上がったソースを貼り付けた為、いきなりInverseModelListRefが定義されており、関連元になるCommentにheadRefプロパティが無いためコンパイルエラーになると思います。本来は双方向の関連(InverseModel(List)Ref)を定義する場合、関連元のModelRefプロパティから定義します。

    同様に、他の2つのModelにもプロパティとアクセッサを追加します。

    Body.java

    package simplebbs.model.bbs;
    
    ~ import省略 ~ 
    
    @Model(schemaVersion = 1)
    public class Body implements Serializable {
    
    ~ key、versionプロパティ省略 ~ 
     
        // 記事本文 
        @Attribute(lob=true)
        private String text;
    
        // Headへの1対1の関連 
        @Attribute(persistent=false)
        private InverseModelRef<Head, Body> headRef =
            new InverseModelRef<Head, Body>(Head.class, HeadMeta.get().bodyRef, this);
     
    ~ アクセッサ省略 ~ 
    
    }

    Comment.java

    package simplebbs.model.bbs;
    
    ~ import省略 ~ 
    
    @Model(schemaVersion = 1)
    public class Comment implements Serializable {
    
    ~ key、versionプロパティ省略 ~ 
     
        // 投稿者名 
        private String username;
        // コメント本文 
        @Attribute(lob=true)
        private String comment;
        // 投稿日時 
        private Date postDate;
    
        // Headへの多対1の関連 
        private ModelRef<Head> headRef = new ModelRef<Head>(Head.class);
     
    ~ アクセッサ省略 ~ 
    
    }

    ◆リレーションシップとは◆

    リレーションシップを使うと、Modelから関連先のModelを簡単に取得できるようになります。

    // HeadからBodyをLazyに取得する 
    Body body = head.getBodyRef().getModel();

    また、関連は初回のアクセス時にデータストアより取得されます。(Lazy Loading)

    リレーションシップの定義方法は少し癖がありますが、参照元から参照先を辿るのはModelRef、参照先から参照元を辿るのがInverseModel(List)Refと覚えるとよいでしょう。詳しくはSlim3公式(日本語はこちら)を参照して下さい。

作成したソースコードは以下になります。

  • simplebbs.model.bbs.Head.java
  • simplebbs.model.bbs.Body.java
  • simplebbs.model.bbs.Comment.java

これでModelの作成は完了です。

次にServiceクラスの作成を行います。