読者です 読者をやめる 読者になる 読者になる

ひこぽんのーと

覚書と雑記です。

JavaEE 7をやってみよう。 JPA その7

JavaEEをやってみよう プログラム

その6のつづき。

今回はエンティティ取得について実装する。
エンティティの取得はEntityManagerというクラスを用いて行う。
EntityManagerにJPQLというJPA用のSQLのようなものを投げることによって、
DB参照ができるようになる。
なんのことはない、やっぱり問い合わせ文は書くのだ。

しかし、全件参照については自動生成したエンティティクラスにすでに定義されている。
今回はそれを呼び出すようにして、SQLを書かずにDB参照するものを作る。

といったところで、ソース。

package ejbModule;

import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import model.Warship;

/**
 * Session Bean implementation class WarshipService
 */
@Stateless
@LocalBean
public class WarshipService implements WarshipServiceLocal {
    @PersistenceContext
    private EntityManager entityManager;
    
    /**
     * Default constructor. 
     */
    public WarshipService() {
        // TODO Auto-generated constructor stub
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public List<Warship> getAllList() {
        return entityManager.createNamedQuery("Warship.findAll", Warship.class).getResultList();
    }

}

まず、メンバにEntityManaerを定義。
@PersistenceContextを付けることで実行時にインスタンスがインジェクションされる。
getAllListメソッドの処理では、EntityManagerのcreateNamedQueryメソッドを呼んでいる。
引数は定義済みJPQLの名前とその型。
Warshipクラスはともかく、"Warship.findAll"ってどこから来たのか、と思うでしょ。
これ、自動生成したWarshipクラスをよく見ると、
クラスに付加されているアノテーションに妙なSQLと一緒に定義されている。

package model;

import java.io.Serializable;
import javax.persistence.*;


/**
 * The persistent class for the WARSHIP database table.
 * 
 */
@Entity
@NamedQuery(name="Warship.findAll", query="SELECT w FROM Warship w")
public class Warship implements Serializable {
  〜〜 略 〜〜
}

createNamedQueryの引数はこれを示している。
ちなみにcreateNamedQueryの戻り値はTypeQueryというクラスで、
これはDBの取得結果ではない。
名前が示す通り、あくまでクエリクラス。
これが持つgetResultListメソッドを呼ぶことで、
ようやっと、DBの抽出結果が得られる、といった仕掛けのようだ。

あと、トランザクションの種類を指定するためにTransactionAttributeアノテーションメソッドに付けてある。
指定するパラメータはTransactionAttributeType.REQUIREDを指定した。
この属性の種類はいくつかあって、用途によって使い分けるようだけれど、
小難しいことはまだわからないので、デフォルトらしいREQUIREDを指定した。
これは当該セッションがトランザクション開始前ならば新たにトランザクションを開始してから処理を実行するが、
すでにトランザクションが開始されている場合は、開始済みであるトランザクションで処理を実行する、
といった意味がある。

他の属性については、ここを見るといいかもしれない。

といったところで、EJBの実装は終わり。
次はビジネスロジックを呼び出すアプリ側の実装に入る。

次回へ続く。