JavaEE/JPA

Last-modified: 2013-06-29 (土) 20:42:18

enum

DB格納時はordinalかnameが保存される。どちらにするかは選択できる。
http://www.slideshare.net/ryoasai/jpa-9109517 17ページ

それ以外の値を使いたい場合は、JAPの実装依存。
EclipseLinkの場合はコンバーターを作成すればよい。
http://brissyu.blogspot.jp/2011/05/rcp-eclipselink.html

サーブレットでもEJBでもないクラスのフィールドに@PersistenceContext

可能だが、そのクラスのインスタンスもコンテナによってnewされる必要があるようだ。
プログラムでFoo f = new Foo();し、f.xxx に@PersistenceContextをつけていても、f.xxx には注入されておらずnullになる。
Fooのインスタンス生成をCDIに管理させれば、f.xxxに注入されるようになる。→JavaEE/CDI

サーブレットからEntityManagerを使う

@PersistenceContext による注入は可能だが、
トランザクションは自分で制御する必要がある。

以下のコードで制御する。

       UserTransaction utx;
       try {
           Context ctx = new InitialContext();
           utx = (UserTransaction)ctx.lookup("UserTransaction");
           // lookupの引数は /UserTransaction とか java:comp/UserTransaction とかの説もあり。
       } catch (NamingException e) {
           throw new ServletException(e);
       }
       try {
           utx.begin();
           やりたい処理
           utx.commit();
       } catch (Exception e) {
           try {
               utx.rollback();
           } catch (Exception e1) {
               e1.printStackTrace();
           }
           throw new ServletException(e);
       }

UserTransactionはコンテナに注入してもらうことも可能。これを利用すれば、上記のようにJNDI lookupをする必要はなくなる。

   @Inject
   private UserTransaction utx;

別の方法として、EntityManager#getTransaction() で EntityTransaction を取得し、そのbegin/commitを呼ぶ方法もあるらしい。

参考

GlassFish 3.1.2.2(内蔵のEclipseLink) で使う

参考

デフォルトのデータソース

管理コンソールの以下で確認できる。

Resources > JDBC > JDBC Resources
→ jdbc/__default が定義されている。
   PoolがDerbyPoolとなっている。
Resources > JDBC > JDBC Connection Pools > DerbyPool
→ Additional Propertiesタブで、接続先(PortNumber, serverNameなどが確認できる。)

persistence.xml

最低限以下の記述が必要。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="boardPU"> <!-- boardPUはアプリから@PersistenceContextで参照している名前 -->
    <properties>
       <!-- テスト用にテーブルを自動的に削除・再作成させたい場合に必要
            無ければ作るの場合は value="create-tables" を指定。
         -->
    	<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

providerとjta-data-sourceも書くべき?

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="boardPU">
    <!-- providerとjta-data-sourceは省略してもとりあえずは動く -->
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/__default</jta-data-source> <!-- GlassFishセットアップ時に自動作成されているデータソース-->
    <properties>
       <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
       <property name="eclipselink.logging.level" value="INFO"/>
    </properties>
  </persistence-unit>
</persistence>

エラー

「connectでエラー」

java.net.ConnectException: ポート 1527 のサーバー localhost への接続中にメッセージ
Connection refused: connect でエラーになりました。

Derbyが起動していない。以下のコマンドで起動する。

asadmin start-database

Could not resolve a persistence unit

cannot Deploy MessageBoard
Deployment Error for module: MessageBoard: Error occurred during deployment:
Exception while  preparing the app : Could not resolve a persistence unit corresponding to
the persistence-context-ref-name [sample.board.Exp/em] in the scope of the module
called [MessageBoard]

@PersistenceContextのunitNameで参照している名前が persistence.xmlのpersistence-unitで定義されていない場合にこのエラーになる。エラーメッセージ中のname [sample.board.Exp/em] が、unitNameとは無関係な名前になっている点に注意。注入先のクラス名/変数名の形になっている。

表またはビュー 'SEQUENCE' は存在しません。

java.sql.SQLSyntaxErrorException: 表またはビュー 'SEQUENCE' は存在しません。

おそらく、DB側に適切にテーブルが作成済みならこのエラーにはならない。
自力で作成するか、persistence.xmlに以下の記述(EclipseLink固有)を追加して、
EclipseLinkに作成させる。

<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>

javax.persistence.TransactionRequiredException

persistence.xmlのpersistence-unitにtransaction-type="JTA"の指定がある場合(transacition-typeを省略した場合も同じ)、EntityManagerのメソッドを使うには、JTAでトランザクションが開始されていないとならない。

Servletの場合、コンテナが自動的にトランザクションを開始してくれるわけではない?
UserTransactionを使って自分で管理する。