2014年8月17日日曜日

【GAE】初級実装編 Slim3モデルクラス作成

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

只今、クラウド基盤「Google App Engine(以下、GAE)」の連載しています。

では、今回よりGAEの目玉である「BigTable」の使い方をご紹介してきます。

ただし、GAEには標準でBigTableを利用する手段が用意されていますが、今回のサンプルアプリではSlim3を導入していますので、Slim3経由でBigTableを使用する方法として、ご紹介致します。

テーブル作成

さて、まずSlim3では「データモデル型」にてデータをやりとりし、それがそのままDBの定義になります。

普通のJavaシステムの場合、まず最初にDBのデータモデル定義があり、後でそれとピッタリに合わせたJavaモデルクラスを作成しますよね?

まあ、先にJavaクラスを作って、後でDBをリバース作成するライブラリもありますが、とにかく普通のシステムの場合は、
テーブルを作る時はJavaのモデル作成とは別途「create table」を発行しています。

Slim3の場合は違いまして、「Javaクラスがそのまま勝手にテーブルになる」という構成です。

Testという名前のクラスを作って保存処理を実行したら、自動的にTestというテーブルが出来て保存されるというカラクリです。

もちろん、テキトーにクラスを作れば良いという話ではなく、ちゃんと指定されたインターフェースを実装したり、アノテーションを宣言したりが必要となりますが、
その辺りはSlim3の自動機能にお任せです。

ビルド

では、さっそく作ってみましょう。

Slim3でプロジェクトを作成すると、以下のような構成になっているはずです。


一番下に「build.xml」がありますよね?
コイツを右クリックから実行します。

すると、以下のような画面が出て来ます。


親切にも色々と作ってくれる機能が揃っておりますが、今回の所は「gen-model-with-dao」を選択します。

MODELクラスとDAOクラスを1:1のセットで作成してくれる機能です。

その次にクラス名を指定する画面が出ますので、Shohinとでもセットします。



これにより、以下のようなShohinモデルのクラスが出来上がりました。
簡単ですね。

@Model(schemaVersion = 1)
public class Shohin implements Serializable {

 private static final long serialVersionUID = 1L;

 @Attribute(primaryKey = true)
 private Key key;

 @Attribute(version = true)
 private Long version;

 /**
  * Returns the key.
  * 
  * @return the key
  */
 public Key getKey() {
  return key;
 }

 /**
  * Sets the key.
  * 
  * @param key
  *            the key
  */
 public void setKey(Key key) {
  this.key = key;
 }

 /**
  * Returns the version.
  * 
  * @return the version
  */
 public Long getVersion() {
  return version;
 }

 /**
  * Sets the version.
  * 
  * @param version
  *            the version
  */
 public void setVersion(Long version) {
  this.version = version;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((key == null) ? 0 : key.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj) {
   return true;
  }
  if (obj == null) {
   return false;
  }
  if (getClass() != obj.getClass()) {
   return false;
  }
  Shohin other = (Shohin) obj;
  if (key == null) {
   if (other.key != null) {
    return false;
   }
  } else if (!key.equals(other.key)) {
   return false;
  }
  return true;
 }
}


フィールド設定

次に、モデルクラスにフィールド変数を定義してテーブルカラムを作成します。

と言っても、「変数名が勝手にDBのカラムになる」というだけですので、普通に「private String shohinId;」とか定義していけばOKです。

その結果がこちら。

/**
 * 商品モデル。
 * 
 * @author Tashiro Endo
 * 
 */
@Model(schemaVersion = 1)
public class Shohin implements Serializable {

 /** シリアルバージョン */
 private static final long serialVersionUID = 1L;

 /** キー */
 @Attribute(primaryKey = true)
 private Key key;

 /** バージョン */
 @Attribute(version = true)
 private Long version;

 /** 商品ID(keyのIDの文字列化) */
 private String shohinId;

 /** 商品名 */
 private String shohinName;

 /** 在庫数 */
 private Integer stock;

 /** 出庫可能日 */
 private Date deliveryDate;

 /** 登録日時 */
 @Attribute(listener = CreationDate.class)
 private Date createdAt;

 /** 更新日時 */
 @Attribute(listener = ModificationDate.class)
 private Date updatedAt;

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((key == null) ? 0 : key.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj) {
   return true;
  }
  if (obj == null) {
   return false;
  }
  if (getClass() != obj.getClass()) {
   return false;
  }
  Shohin other = (Shohin) obj;
  if (key == null) {
   if (other.key != null) {
    return false;
   }
  } else if (!key.equals(other.key)) {
   return false;
  }
  return true;
 }

 /**
  * キーを取得します。
  * 
  * @return キー
  */
 public Key getKey() {
  return key;
 }

 /**
  * キーを設定します。
  * 
  * @param key キー
  */
 public void setKey(Key key) {
  this.key = key;
 }

 /**
  * バージョンを取得します。
  * 
  * @return バージョン
  */
 public Long getVersion() {
  return version;
 }

 /**
  * バージョンを設定します。
  * 
  * @param version バージョン
  */
 public void setVersion(Long version) {
  this.version = version;
 }

 /**
  * 商品ID(keyのIDの文字列化)を取得します。
  * 
  * @return 商品ID(keyのIDの文字列化)
  */
 public String getShohinId() {
  return shohinId;
 }

 /**
  * 商品ID(keyのIDの文字列化)を設定します。
  * 
  * @param shohinId 商品ID(keyのIDの文字列化)
  */
 public void setShohinId(String shohinId) {
  this.shohinId = shohinId;
 }

 /**
  * @inheritDoc
  */
 @Override
 public String toString() {

  StringBuilder bul = new StringBuilder();

  bul.append("key=").append(key).append(",");
  bul.append("version=").append(version).append(",");
  bul.append("shohinId=").append(shohinId).append(",");
  bul.append("shohinName=").append(shohinName).append(",");
  bul.append("stock=").append(stock).append(",");
  bul.append("deliveryDate=").append(deliveryDate).append(",");
  bul.append("createdAt=").append(createdAt).append(",");
  bul.append("updatedAt=").append(updatedAt);

  return bul.toString();
 }

 /**
  * 商品名を取得します。
  * 
  * @return 商品名
  */
 public String getShohinName() {
  return shohinName;
 }

 /**
  * 商品名を設定します。
  * 
  * @param shohinName 商品名
  */
 public void setShohinName(String shohinName) {
  this.shohinName = shohinName;
 }

 /**
  * 在庫数を取得します。
  * 
  * @return 在庫数
  */
 public Integer getStock() {
  return stock;
 }

 /**
  * 在庫数を設定します。
  * 
  * @param stock 在庫数
  */
 public void setStock(Integer stock) {
  this.stock = stock;
 }

 /**
  * 出庫可能日を取得します。
  * 
  * @return 出庫可能日
  */
 public Date getDeliveryDate() {
  return deliveryDate;
 }

 /**
  * 出庫可能日を設定します。
  * 
  * @param deliveryDate 出庫可能日
  */
 public void setDeliveryDate(Date deliveryDate) {
  this.deliveryDate = deliveryDate;
 }

 /**
  * 登録日時を取得します。
  * 
  * @return 登録日時
  */
 public Date getCreatedAt() {
  return createdAt;
 }

 /**
  * 登録日時を設定します。
  * 
  * @param createdAt 登録日時
  */
 public void setCreatedAt(Date createdAt) {
  this.createdAt = createdAt;
 }

 /**
  * 更新日時を取得します。
  * 
  * @return 更新日時
  */
 public Date getUpdatedAt() {
  return updatedAt;
 }

 /**
  * 更新日時を設定します。
  * 
  * @param updatedAt 更新日時
  */
 public void setUpdatedAt(Date updatedAt) {
  this.updatedAt = updatedAt;
 }
}

単純にフィールド変数を追加して、getter/setterを自動出力すればOKです。
getter/setterは必須ですので、ご注意を。

なお、上記では「String」「Integer」が追加されていますが、これは何でもアリというわけではなく、限られた一部のクラスしかフィールドとして定義してはいけません。


  • 500文字以下の短い文字列の場合は、String
  • 整数なら、Ingeter
  • Ingeterで収まらない大きい数字の場合は、Long
  • 日付の場合は、Date


こんな感じに決まっています。
直感で大体分かると思いますが、公式サイトにちゃんとした一覧がありますので、必読です。


アノテーション「@Attribute」の「CreationDate.class」と「ModificationDate.class」

上のソースをご覧になると気付かれたかと思いますが、モデルクラスには「@Attribute」というアノテーションがフィールドに付与されているものがありまして、
これがモデルクラス特有の役割を持ちます。

「(primaryKey = true)」とか大事な機能につきましては、次回以降について記事にするとしまして、
今回の所は小ネタ機能である「CreationDate.class」と「ModificationDate.class」についてご紹介します。

これは、「登録日と更新日を自動セットする」という機能です。
これについても上記URLに記載があります。

「登録日と更新日」は、まあこれから作るシステム上、特に要件には考慮されていないものですけれども、保存しておいて損は無い情報ですよね?
なので、私は全モデルクラスに、この登録日と更新日は持たせるということでルールを統一して作っています。

この記事ではソースを張る都合でShohinクラスに実装していますが、実際には「AbstractModel」というクラスを自分で作って、
そこに「CreationDate.class」と「ModificationDate.class」を定義しています。

モデルクラスは継承も出来ますので、共通で使うフィールドは継承してOK!!


このように、Slim3は探してみるとチョコチョコ便利な機能が色々揃っていたりしてくれていますので、
公式サイトを見ながらあれこれ実験してみると面白いですね。


終わりに

以上で、通常システムで言う所の「create table」が完了した状態にあります。

次回は、実際にレコードを登録する「insert」に該当する機能の実装を行います。

0 件のコメント:

コメントを投稿