LoginSignup
16
15

More than 5 years have passed since last update.

JavaEE6をいじったときのメモ

Last updated at Posted at 2014-09-15

JPAについて

JPAの参照系について

getResultList()の検索件数0件のときはどんな動きになる?

  • Size = 0のリストが帰ってくる感じです (nullじゃないので注意)。

entityの静的クエリはじぶんで追加してっていいんだよね?

  • なんか、普通に追加したら not foudと言われてしまった……
@NamedQueries({
:
@NamedQuery(name = "Customer.findByIdAndName", query = "SELECT c FROM Customer c WHERE c.customerId = :customerId AND c.name = :name")})
public class Customer implements Serializable {
:
Caused by: java.lang.IllegalArgumentException: NamedQuery of name: Customer.findByIdAndName not found.

結局、なんかデバッガ起動したりしてたら、何も変えずにちゃんと動きました。
意味がわかりませんが、コンテナ?が、追加した@NamedQueryをちゃんと認識するためのトリガーがあるのかな??


JPAの更新系について

  • トランザクションは em.getTransactionでやればOKと思ってたけどこんなんでた。
public void updateCustomers(Customer customer){
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        em.merge(customer);
        tx.commit();
}
Caused by: java.lang.IllegalStateException: 
Exception Description: Cannot use an EntityTransaction while using JTA.
at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.getTransaction(JTATransactionWrapper.java:73)

なんか、JavaEEのトランザクションには種類があるっぽい。JTAトランザクションを使うべきところなのに、別のトランザクション使うなよってことかな?
以下のブログによると、persistence.xmlのなかで、RESOURCE_LOCAL/NON-JTA-DATA-SOURCE/JTA-DATA-SOURCEのいずれかが指定されているらしい。
http://nwing.knowd.co.jp/yamazaki/?q=node/118

JTA-DATA-SOURCE
JTAを使って、トランザクションを管理します。
この場合、EntityManager#getTransactionによるトランザクション制御はできなくなります。トランザクションの制御はコンテナが行う(CMT - Contena Manged Transaction)ので、EJBの宣言性トランザクションを使用するか、または、UserTransactionを取得します。EJBと関連が強くなります。

もし、JTA-DATA-SOURCEを使用しているにもかからずEntityManager#getTransactionから取得したEntitTransactionを使用すると、次の例外が発生します。

Exception Description: Cannot use an EntityTransaction while using JTA.

ということみたい。で、JTAを利用する場合のトランザクションはUserTransactionでやってねということらしい。以下のようなかんじで書けばいいっぽい。

@Resource
UserTransaction utx;
:
public void updateCustomers(Customer customer){
        // 例外処理省略
        utx.begin();
        em.merge(customer);
        utx.commit();
}

……と思ったらやっぱりダメ。

Caused by: javax.naming.NameNotFoundException: java:comp/UserTransactionのルックアップは、コンテナで管理されるトランザクションBeanでは許可されません
 :
... 63 more

ほんとストレスたまるわ!!
 :
 :

金魚本9章読んだら解決しました!!

EJB内でのトランザクションの管理方法は2種類あるらしい。

CMT(コンテナ管理トランザクション)

トランザクションの開始、コミット、ロールバックをコンテナが自動管理

BMT(Bean管理トランザクション)

トランザクションの開始、コミット、ロールバックをBean内に記述(@TransactionManagementの指定が必要)。

より細かいトランザクション管理が必要(一つのメソッドで複数トランザクションを管理したい場合など)な時は、BMTを採用するといいみたい。
BMTでやる場合はこんな感じでやればOK。

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class CustomerSessionBean {
 :
    @Resource
    UserTransaction utx;
 :
    public void updateCustomers(Customer customer){
        // 例外処理は省略
       utx.begin();
       em.merge(customer);
       utx.commit();
}

すごく簡単に言えば、CMTはトランザクションを自動的に管理してくれる(デフォルトはこっち)。
要するに、CMTでトランザクション管理してるから、BMTは許可できないよってことだったみたい。

EJBについて

@Injectの動きについて

@Inject, @Producer

以下参照
http://typea.info/blg/glob/2014/05/java-ee-4-java-ee-didependency-injection-cdicontexts-and-dependency-injection.html

@EJB

EJBのリモート&ローカル・インターフェース、インターフェースのないビュー参照を注入。
要するに、コンテナで動いてたりするEJB(セッションBean)への参照を注入している感じ。

@Resource

JDBCデータソース、セッション・コンテキスト、ユーザ・トランザクション等の参照を注入

@Remote, @Local

セッションBeanのリモートインターフェース、ローカルインターフェース(別のセッションBean用のインターフェース)を定義する。

@Local
public interface CustomerManegerLocal {
    List<Customer> getCustomers();
    List<Customer> getCustomersById(int id);
    void updateCustomers(Customer customer);
}

@Remote
public interface CustomerManegerRemote {
    List<Customer> getCustomers();
    List<Customer> getCustomersById(int id);
    void updateCustomers(Customer customer);
}

// セッションBeanでの実装
@Stateless
public class CustomerManeger implements CustomerManegerLocal, CustomerManegerRemote {
 :
 :
}

呼び出しがわ

@Stateless
@Path("/customers")
public class CustomerSessionBean {
    // セッションBean間のローカル呼び出しなので、
    // CustomerManegerLocalに注入する必要がある。
    @Inject CustomerManegerLocal cm;
 :
 :

その他

変なビルド失敗について

なんかMavenで新しくプロジェクトを作ってみたら、以下のエラーがでてデプロイできなくなった。

Exception Description: Entity name must be unique in a persistence unit. Entity name [MicroMarket] is used for the entity classes [com.mycompany.customermng.MicroMarket] and [com.mycompany.customermng.entities.MicroMarket].

なんかパッケージ名を変えたときのゴミが残ってたみたい。消去してビルドをやったら上手くいった。

16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15