Playフレームワークピックアップの4:ドメインモデルとJPAサポート

4431 ワード

1、属性シミュレーション
Modelの場合、Playのフィールドはpublic修飾子ですが、フレームワークではsetterとgetterが自動的に生成されます.
@Entity
@Table(name="product ")
public class Product extends BaseModel{
  @Id
  public Long id;
  public String name;
}

プレイを実行してclassファイルを取得し、javapコマンドで次のことがわかります.
E:\>javap PrintTemplateType
Compiled from "Product .java"
public class models.Product extends models.BaseModel{
public java.lang.Long id;
public java.lang.String name;
public models.Product ();
public java.lang.Long getId();
public void setId(java.lang.Long);
public java.lang.String getName();
public void setName(java.lang.String);
... //             
}

また、他の場所では、このようなフィールドがsetterとgetterに置き換えられます.すでにカスタムメソッドがある場合は、フレームワークが手動で作成するメソッドを優先します.
2、データ持続化
Play 1.x永続層はHibernateを採用しており、注記エンティティを使用する場合は、HibernateではなくJPAパッケージの@Entityを使用する必要があります.プレイから直接db.jpa.JPAオブジェクトには、Modelをデータベースに永続化したり、HQL文を実行したりするエンティティマネージャがあります.たとえば、次のようになります.
EntityManager em = JPA.em();
em.persist(product);
em.createQuery("from Product where price > 50").getResultList();

PlayエンティティはActiveRecordモードを採用し、Strutsのdaoとpojoを統合し、ActiveRecordもORM層に属し、Railsが最初に提案した標準的なORMモデルに従う:表は記録にマッピングされ、記録はオブジェクトにマッピングされ、フィールドはオブジェクト属性にマッピングされる.従うネーミングと構成慣例に合わせて,モデルの操作を大幅に迅速に実現でき,簡潔で分かりやすい.PlayもActiveRecordモードでの迅速な開発を提唱しており、その主な考え方は以下の通りである.
  • 各データベーステーブルはクラスを作成し、クラスの各オブジェクトインスタンスはデータベース内のテーブルのローレコードに対応する.通常、テーブルの各フィールドにはクラスに対応するFieldがあります.
  • ActiveRecordは同時に自己持続化を担当し、ActiveRecordにデータベースへのアクセス、すなわちCURDをカプセル化した.
  • ActiveRecordは、ビジネスロジックの一部をカプセル化したレルムモデルです.

  • 3、無状態モデル
    Playは、アプリケーションの完全な無状態化を維持するために「共有なし」のアーキテクチャとして設計されている.このような利点は、1つのアプリケーションを同じ時点で複数のサーバノード上で実行できることです.Layはモデルの無状態化を維持するために、一般的なトラップを避ける必要があります.最も重要なのは、マルチリクエストのためにJavaスタックにオブジェクトを保存しないことです.キャッシュの使用は非常に良い選択であり、Javaサーブレットセッションの良い代替案でもあります.
    4、JPAサポート
    JPA(Java Persistence API)はJava永続化の仕様であるが、JPA自体は永続化の具体的な実現ではない.現在、JPAの実現は主にHibernate、OpenJPA、Toplink、JDOなどがある.PlayではHibernateの実装がデフォルトで使用されており、JPAは仕様として使用されるため、Hibernateの代わりに他の任意のJPA実装を使用することも可能である.JPAエンティティーマネージャが起動すると、プログラムコードには、JPA補助クラスによって管理されているエンティティーが取得されます.例:
    public static void index(){
      Query query = JPA.em().createQuery("from Article");
      List<Article> articles = query.getResultList();
      render(articles);
    }

    トランザクション(Transaction)は、データベース内の様々なデータ・アイテムにアクセスして更新するプログラム実行ユニットです.Playは自動的にトランザクション管理を行い、HTTPリクエストを送信するたびに自動的にトランザクションを開き、HTTPレスポンスを送信した後にトランザクションをコミットする.プログラムがrequest/response中に例外を投げ出した場合、トランザクションは自動的にロールバックされます.もちろんJPAを明示的に呼び出すこともできます.setRollbackOnly()メソッドは、現在のトランザクションをコミットせずにコード内でトランザクションを強制的にロールバックするようにJPAに通知します.play.db.jpa.Modelクラスでは、クエリーの結果をページングするためのさまざまな方法が用意されています.
    //     100  post
    List<Post> posts = Post.all().fetch(100);
    
    //  50 post    ,        100 post
    List<Post> posts = Post.all().from(50).fetch(100);
    
    Play   count()               :
    long postCount = Post.count();
    long userPostCount = Post.count("author = ?", connectedUser);

    Playでは完全なJPQL文を書いて検索することもできます.
    Post.find(
    "select p from Post p, Comment c " +
    "where c.post = p and c.subject like ?", "%hop%"
    );

    また、JPQL文には、条件部分のクエリのみを書き込むこともできます.
    Post.find("title", "My first post").fetch();
    Post.find("title like ?", "%hello%").fetch();
    Post.find("author is null").fetch();
    Post.find("title like % and author is null", "%hello%").fetch();
    Post.find("title like % and author is null order by postDate", "%hello%").fetch();
    Post.find("order by postDate desc").fetch();

    Hibernateは、データベースでクエリーされた結果をオブジェクトキャッシュとして維持します.エンティティマネージャがクエリーマッチングなどの操作を行う間、データは永続的なオブジェクトとして存在します.これは、トランザクションがコミットされていない場合、オブジェクトの変更が自動的にデータベースに永続化されることを意味します.JPAの仕様は、オブジェクトの変更のデフォルトがトランザクション・プロシージャと一致するため、メソッドを明示的に呼び出すことなく、変更後のデータを永続化できるように定義されています.このような全自動の永続化管理は、オブジェクトが変更されると永続化されることを常に望んでいないため、不足する点もあります.したがって、エンティティマネージャにオブジェクトの更新を通知するよりも、更新する必要のないオブジェクトを通知します.refresh()メソッドは、単一のエンティティをロールバックし、トランザクションがコミットされる前に呼び出され、オブジェクトが永続化されません.次のようになります.
    public static void save(Long id) {
      User user = User.findById(id);
      user.edit("user", params.all()); //        
      validation.valid(user);
      if(validation.hasErrors()) {
        //       user  
        user.refresh();
        edit(id);
      }
      show(id);
    }