slim3itを参考に関連のお勉強

まず、genの使い方を試してみた。すごく楽です。すばらしい。
今回はslim3itのトップページから新たなリンクを作って、とっても実用的な猫管理システムを作ってみることにした。
まずは
ドキュメントに書いてあることメモ

関連付けられるクラスのクラスをタイプとして持つフィールドを使用します。

非所有関係は自然構文では現在サポートされていませんが、フィールドにデータストア キーを直接保存することで関係を管理できます。


具体的には↓
http://d.hatena.ne.jp/higayasuo/20090723/1248315116
分かりやすい。なるほど。


昨日slim3を使わずにいろいろ関連試してみて、できなかったことが、Slim3でやったらできた。何でできたのかはまだわからないし、これで正しいのかも分からないのだけれどもとりあえず勉強途中経過メモとして書いておく。


まずエンティティはCatとKindを作ります。というかgenが自動でDaoとMetaとEntityを作ってくれます。フィールドは双方ともにnameを追加する。関連の作り方については先ほどのひがさんのページを参考にさせていただき、非所有関連を作ってみました。

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
@Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version")
public class Cat implements Serializable {

    private static final long serialVersionUID = 1L;

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String key;

    @Persistent
    private Long version = 1L;

    @Persistent
    private String name;

    @Persistent
    private String kindKey;


    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }

    public Long getVersion() {
        return version;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Kind getKind() {
        if (kindKey == null) {
            return null;
        }
        return JDOHelper.getPersistenceManager(this).getObjectById(Kind.class, kindKey);

    }
    public void setKind(Kind kind) {
        if (kind == null) {
            kindKey = null;
        }
        kindKey = kind.getKey();

    }
}
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
@Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version")
public class Kind implements Serializable {

    private static final long serialVersionUID = 1L;

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String key;

    @Persistent
    private Long version = 1L;

    @Persistent
    private String name;


    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }

    public Long getVersion() {
        return version;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


猫種類の登録画面

これを受けるInsertKindController.java

public class InsertKindController extends Controller {

    @SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(InsertKindController.class.getName());

    private KindDao dao = new KindDao();

    @Override
    public Navigation run() {
        Kind kind = new Kind();
        BeanUtil.copy(request, kind);
        dao.makePersistentInTx(kind);
        return redirect(basePath);
    }
}

これはBlogアプリの丸パクリです。copyメソッドはrequestのパラメータ名を見て値をkindに自動的に設定してくれている。それで、永続化してコンテキストパスに戻ります。


何種類か登録したあとの猫種類一覧画面。


次に猫を登録します。
猫登録画面。

先ほど登録した猫種類はセレクトボックスで選択する。jspはこれまたslim3itを参考にさせていただいております。ありがとうございます。

<%@page pageEncoding="UTF-8" isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@taglib prefix="f" uri="http://www.slim3.org/functions"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>cat CreateCat</title>
<link rel="stylesheet" type="text/css" href="/css/global.css" />
</head>
<body>
<form action="${f:url('insertCat')}" method="post">
猫種<br />
<select name="kindKey">
<c:forEach var="kind" items="${kindlist}">
<c:set var="kindkey" value="${kind.key}"/>
<c:set var="kindname" value="${kind.name}"/>
<option ${f:select("cat", kindkey)}>${kindname}</option>
</c:forEach>
</select>
<br />
お名前<br />
<input type="text" ${f:text("name")}/><br />
<input type="submit" value="Insert"/>
</form>
</body>
</html>


これをsubmitすると、選択したKindのencoded-keyがkindKeyの名前で、送信されます。

これを受けるInsertCatController.java

public class InsertCatController extends Controller {

    @SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(InsertCatController.class.getName());

    private CatDao cdao = new CatDao();
    private KindDao kdao = new KindDao();

    @Override
    public Navigation run() {
        Cat cat = new Cat();
        //BeanUtil.copy(request, cat);
        Kind kind = kdao.find(param("kindKey"));
        cat.setKind(kind);
        cat.setName(param("name"));
        cdao.makePersistentInTx(cat);
        return redirect(basePath);
    }
}

param(String)で、パラメータ名を指定して該当の値を取得できるみたいなのでこうしてみて、catにkind(実際セットされるのはエンコードされた文字列)とnameを設定して、永続化すると登録できました。slim3すばらしい。楽。


昨日、普通のサーブレットで同じことをやってたんですが、同じことをやってたつもりなんだけれどCatを登録するときに主キーが自動で生成されなかったような気がするのだけれど、気のせいかな。確認してないのでなんともいえないのだけれど。できるのかもしれない。非所有関連で作っておけば、関連先は単なるStringになるので、親子とか同じエンティティグループとか考えなくてもこの場合は、ひとつのEntityをpersistすることになるので問題ないという理解でいいのでしょうかね。そうですよね。いろいろなエンティティを同時にトランザクションにするってのは、こう考えると大変なことなんじゃないか?そんなことはしないのか?分からない。少しずつ勉強します。