kagamihogeの日記

kagamihogeの日記です。

JBoss AS 7 + Oracle 11g

JBoss AS 7からOracle 11gに繋いでJPAを試したかったので。

2012/10/28 追記 ここから

6.0 以前は設定ファイルを直接編集する方法がメインでしたが、7 以降は管理コンソールを使う方が標準的な方法になるようです。
JBoss AS 7.1.0 でのデータソース定義(DB2 for i) - i am BEST - livedoor Wiki(ウィキ) より抜粋

とか書いてる人がいる。なので、AS 7へのデータソース追加は、自分のこのエントリで書いてるような直接XMLを編集するのは古いやり方に属するかも。
2012/10/28 追記 ここまで

こんな環境でやりました

なお、このエントリを書くにあたってはJava @ Work: Oracle / PostgreSQL Datasource in JBoss AS 7を参考にしています。

やったこと

まずJBoss Toolsプラグイン入れるともれなく下図のようなJBoss CentralとかいうJBossのポータルのようなものを表示するビューも同梱されてくる。Create Projects -> Java EE Web Projectを選択すると雛形を作ってくれるので、このエントリではコレを利用する。なお、スクリーンショットのDescriptionにもあるとおり、ここからプロジェクトを作るにはJBoss AS 7とMaven 3(というかm2eプラグイン)は先に使える状態にしておく必要がある。

というわけでプロジェクト作ると、Java EEプロジェクト作られてMavenに沿ったディレクトリ構成作られてJPA用のpersistence.xml作られてと、ひとまずの準備はコレで完了。

次に、データソースであるOracleに接続できるような設定をしていくわけだけど、大きく2種類の作業が必要。一つはデプロイつーかJPA用のpersistence.xmlに書くデータソースの書き換えで、これはJPAとして汎用的な記述。もう一つはJBossからOracleへのデータソース接続の設定で、こちらはJBoss AS 7に固有の設定を書く必要がある。

persistence.xmlの修正

src/main/resources/META-INF/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="database">
   <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
   <properties>
     <property name="hibernate.show_sql" value="true" />
   </properties>
  </persistence-unit>
</persistence>
JBossのModuleの追加

詳しいことは俺自身よくわかってないので省略してしまうが、兎に角JBoss AS 7ではデータソースの設定はJBoss ASのModuleとして登録する必要がある。

まず%JBOSS_HOME%/standalone/configuration/standalone.xmlを下記のように編集する。persistence.xmlのデータソース名とここのjndi-nameが一致してれば一先ずはOK.

        <subsystem xmlns="urn:jboss:domain:datasources:1.0">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
                    <security>
                        <user-name>kagamihoge</user-name>
                        <password>xxxxxxxxxx</password>
                    </security>
                    <driver>oracle</driver>
                </datasource>
                <drivers>
                    <driver name="oracle" module="com.oracle.db">
                        <datasource-class>oracle.jdbc.OracleDriver</datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

次にJDBCドライバを実際にModuleとして登録する設定を書く。%JBOSS_HOME%/modules/com/oracle/db/main/というディレクトリを作り、同ディレクトリにJDBCドライバであるojdbc6.jarを置いて、同ディレクトリにmodule.xmlというファイルを作る。module.xmlの中身は下記のような感じ。

<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.1" name="com.oracle.db">

    <resources>
        <resource-root path="ojdbc6.jar"/>
        <!-- Insert resources here -->
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

これで準備OK、あとはJava側でコードを書く。下記はサンプルのプロジェクトからそのまんまコピペのコード。サンプルはCDIが設定してあるため、アノテーション書けばEntityManagerのインスタンスが注入されるので、そっからJPAでデータアクセスするコードが書ける。

@RequestScoped
public class MemberListProducer {
    @Inject
    private EntityManager em;

    @PostConstruct
    public void retrieveAllMembersOrderedByName() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        ...
    }
}
その他

バージョンによるのかもしれないが、hibernate.dialectのプロパティが無いとかでJPAというかHiberenateが起動しないときがある。ダイアレクトを指定してやればいいんだが、しかし困ったことにhiberenate-core-4.1.0.Final.jarにはOracle 11g用のダイアクレトのクラスが存在しない。しかし、件のエントリによると「無いなら作ればいいじゃない(意訳)」ということらしく、とりあえずは下記のようなクラスを普通に作ってしまえばよい。

package org.hibernate.dialect;

import java.sql.Types;

public class Oracle11gDialect extends Oracle10gDialect {
    public Oracle11gDialect() {
        registerColumnType(Types.BOOLEAN, "number(1,0)");
    }
}

上記はschema autocreationを使う場合らしい*1ので、要らなければOracle10gDialectをプロパティに指定しても良いかもしれないが、試してないんで分からない。

persistence.xmlはこうなる。

   <properties>
     <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle11gDialect" />
     <property name="hibernate.show_sql" value="true" />
   </properties>

また、org.hibernate.dialect.*がビルドに必要となる関係でpom.xmlhibernate-coreの依存性を追加する。

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>4.1.0.Final</version>
  <scope>provided</scope>
</dependency>

*1:というのは俺がschema autocreation使ったことないので