Google App Enginでぶち当たった問題 その2
最初に実装でぶつかった問題はJPAのコードの書き方。
GEAのJPAはDataNucleus Enhancer (version 1.1.0)を利用し無ければならないのだがコード作法があるようです。
サンプルですがアカウントの作成をするコードです。
public void addAccount(Account account) { EntityManager em = null; EntityTransaction tx = null; try { em = EMF.get().createEntityManager(); tx = em.getTransaction(); tx.begin(); em.persist(account); tx.commit(); } catch (Exception e) { if (em != null && tx != null) { if (tx.isActive()) { // TODO must implement Log System.out.println("Insert could not execute, Rollbacking..."); tx.rollback(); } } } finally { em.close(); } }
これは普通です。
でアカウントを削除する場合には
public void removeAccount(Account account) { EntityManager em = null; EntityTransaction tx = null; try { em = EMF.get().createEntityManager(); tx = em.getTransaction(); tx.begin(); Account delete = em.find(Account.class, account.getAccountId()); em.remove(delete); tx.commit(); } catch (Exception e) { if (em != null && tx != null) { if (tx.isActive()) { // TODO must implement Log System.out.println("Remove could not execute, Rollbacking..."); tx.rollback(); } } } finally { em.close(); } }
これは普通です。
で検索を行う場合には
public Long findAccountByNickName(String nickname) { EntityManager em = null; EntityTransaction tx = null; List<Account> accounts = null; Long id = new Long(0); try { em = EMF.get().createEntityManager(); tx = em.getTransaction(); tx.begin(); Query query = em.createQuery("SELECT a FROM Account" + " a WHERE a.accountName = ?1"); query.setParameter(1, nickname); accounts = (List<Account>) query.getResultList(); tx.commit(); if (accounts.equals(null)) { LOG.info("No record in account table"); } else if (accounts.size() > 1) { LOG.info("duplicate record error in account table"); } else { for (Account account : accounts) { id = account.getAccountId(); } } } catch (Exception e) { e.printStackTrace(); } finally { em.close(); } return id; }
とかいても動きません。
Query query = em.createQuery("SELECT a FROM " + Account.class.getName() + " a WHERE a.accountName = ?1");
と書き直すと動きます。
たぶんテーブル構造がクラスに依存しているからでしょう・・
あとちょっとしたバグも発見しました。
プロジェクト名が info.hogehoge.gwt.... とかになると infoの部分はDataNucleus Enhancerがうまくパースできないようです。
http://code.google.com/p/datanucleus-appengine/issues/detail?id=35&can=1&q=info&colspec=ID%20Type%20Status%20Priority%20FoundIn%20TargetRelease%20Owner%20Summary
こちらに同じ問題がかいておりました。
JPAのテーブル構造を表すエンティティクラスでもははまりました。
エンティティクラスを作るときに @idをlong プリミティブ型を利用していたのですが、最初は全く気付かずはまりました・・Longのラッパーに変更しなければ動きません。
@Entity public class Account { @Id @GeneratedValue(strategy = IDENTITY) private Long accountId; private String accountName; private String email; private String gender; private Date registDate; private Date birthDay; //以下setter getter----
次回はJunitでテストを行う際に戸惑った問題を書きます。