主キーを任意のカラムに変更する

slim3のデータクラスは、Keyクラスでなければならないようです。
https://sites.google.com/site/slim3documentja/documents/slim3-datastore/defining-data-classes

でも、ユーザの情報を格納するデータクラスはemailアドレスにしたいですし、emailアドレスで検索したいです。
いろいろやり方はあるようです。
http://d.hatena.ne.jp/higayasuo/20091111/1257905482
http://www.tdtsh.com/blog/archives/759
が、今回はユーザに紐づく情報(同一タイミングで別の更新が入ることを考慮しない)こともあり、てきとーに組んでみました。

package hm.orz.chaos114.gae.rsspocket.dao;

import hm.orz.chaos114.gae.rsspocket.model.UserInfo;

import java.util.List;
import java.util.concurrent.Future;

import org.slim3.datastore.DaoBase;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.EntityNotFoundRuntimeException;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

public class UserInfoDao extends DaoBase<UserInfo>{

    @Override
    public Key put(final UserInfo model) {
        setKeyIfNull(model);
        return super.put(model);
    }

    @Override
    public List<Key> put(final List<UserInfo> models) {
        // 利用しないため未実装
        throw new UnsupportedOperationException("未実装");
    }

    @Override
    public Future<Key> putAsync(final UserInfo model) {
        setKeyIfNull(model);
        return super.putAsync(model);
    }

    @Override
    public Future<List<Key>> putAsync(final List<UserInfo> models) {
        // 利用しないため未実装
        throw new UnsupportedOperationException("未実装");
    }

    /**
     * Userが一致するUserInfoオブジェクトを取得する。
     * 
     * @param user ユーザ情報
     * @return UserInfoオブジェクト
     */
    public UserInfo getByUser(final User user) {
        final Key key = createKey(user);
        try {
            return get(key);
        } catch (final EntityNotFoundRuntimeException e) {
            return null;
        }
    }

    /**
     * Keyが設定されていない場合は、設定されているUserからKeyを生成し、設定する。
     * 
     * @param userInfo ユーザ情報モデル
     */
    private void setKeyIfNull(final UserInfo userInfo) {
        if (userInfo.getKey() == null) {
            userInfo.setKey(createKey(userInfo.getUser()));
        }
    }

    private Key createKey(final User user) {
        return Datastore.createKey(UserInfo.class, user.getEmail());
    }
}

put系のメソッドをオーバーライドし、Userのemailより作成したKeyを設定しています。
また、getByUserにて、指定されたUserオブジェクトのemailよりKeyを作成し、取得しています。
(put系のListを引数にとるメソッドを利用する予定が無かったので、実行時に例外となるようにしてあります。使うことがあれば、実装する予定です。)


現在開発中のものより抜粋(https://github.com/noboru-i/rsspocket