データロードアプリケーションのJPAプロバイダーとしてHibernate3.2.5とHibernateAnnotations3.3.1.GAを使用しています。接続プールにC3P0を使用するようにHibernateを構成しました。
私のデータベースは次のとおりです。OracleDatabase11gEnterpriseEditionリリース11.1.0.7.0-64ビット本番
11gにはHibernate方言が組み込まれていないため、使用するように構成しました
org.hibernate.dialect.Oracle10gDialect
JDBCドライバー:Oracle JDBCドライバー、バージョン:11.2.0.1.0
アプリケーションは、後で分析およびレポートするために、メインフレームシステムからOracleDBにトランザクションパフォーマンスログをロードします。これは基本的に、フォルダーを監視して新しいファイルを待機し、それを読み取ってデータベースに挿入するバッチジョブです(1日あたり平均約450万行が挿入されます)。したがって、JDBCバッチ挿入を使用できるため、Hibernateを選択しました。いくつかの比較テストの後、EclipseLinkではあまりうまく機能しないように見えました。ファイルは独自のバイナリ形式であるため、CSVインポートなどのより単純なツールを使用することはできません。
もともとはワークステーションでMySQLを使用するためのアプリケーションを開発しましたが、これは元々は分析タスク用でしたが、データのインポートと保持を継続することが有用であることが証明されたため、エンタープライズOracleRACプラットフォームに移動したいと考えています。私自身と他の数人のアナリストが使用するために、2、3か月間それを使用します。DBAにテーブルを構成させ、フィールド名とデータ型の小さな変更を反映するようにエンティティクラスを調整し、ドライバーと接続の詳細などを変更しましたが、主キーの生成でいくつかの問題が発生しました。
いくつかのテーブルがあります(トランザクションタイプ、ユーザーコードなどのさまざまなサポートタイプを格納するいくつかのテーブルを含むメインデータテーブル)。それぞれに、シーケンスと更新前のトリガーを使用して自動生成される一意の(プライマリ)ID列があります。
DBAは、作成したユーザーが表示できないようにシーケンスを構成しました。
JPA(javax.annotations)の生成値タイプを使用しても、どのような場合でも機能しません。
例えば:
@GeneratedValue(strategy = GenerationType.AUTO)
これにより、SQLが得られます。
select hibernate_sequence.nextval from dual
Oracleドライバがエラーで例外をスローするもの:
25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2289, SQLState: 42000
25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02289: sequence does not exist
調査を行った結果、Hibernate JPAアノテーション拡張機能「GenericGenerator」を「select」戦略で使用するオプションを見つけました(http://docs.jboss.org/hibernate/stable/core/reference/en/html/ mapping.html#mapping-declaration-id-generator)
例えば
@GeneratedValue(generator="id_anEntity")
@GenericGenerator(name = "id_anEntity",
strategy = "select")
ただし、これを使用すると、EntityManagerFactoryの作成中にHibernateがハングすることがわかります。プロパティの構築、名前付きクエリの構築、サーバーへの接続を通過した後、次の場所でハングアップするようです。
25/11/2009 1:40:50 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
戻ってこない。
persistence.xmlファイルで方言を指定しなかった場合にも同じことが起こることがわかりました。
「インクリメント」戦略を使用すると問題なく動作しますが、これは、シーケンスがインクリメントされずに値がインクリメントされたためにシーケンスが中断されることを意味します。これは理想的とは言えません。
「ネイティブ」ストラテジーは、GenerationType.AUTOを使用した場合と同じ出力を提供します(ORA-02289:シーケンスは存在しません)。
これが間違ったキー生成戦略を使用したことが原因なのか、構成のエラーなのか、バグなのかはわかりません。
「選択」戦略を機能させるための支援、またはより良い代替案を歓迎します。プリペアドステートメントなどで純粋なJDBCを使用することに戻る可能性がありますが、これは少し厄介になる傾向があり、JPAアプローチを好みます。
いくつかの詳細:
Persistence.xmlプロパティ:
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.timeout" value="1800"/>
<property name="hibernate.c3p0.max_statements" value="100000"/>
<property name="hibernate.jdbc.use_get_generated_keys" value="true"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.cache.use_second_level_cache" value="false"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<property name="hibernate.connection.username" value="myusername"/>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
<property name="hibernate.connection.password" value="mypassword"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP) (HOST = myoracleserver) (PORT = 1521))
(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = myservicename))
)"/>
<property name="hibernate.jdbc.batch_size" value = "100000" />
アノテーションを使用したエンティティクラスの1つでのIDフィールドの宣言のサンプル:
@Entity
@Table(name = "myentity",
catalog = "",
schema = "mydb")
public class myEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(generator="id_anEntity")
@GenericGenerator(name = "id_anEntity",
strategy = "select")
@Column(name = "MYENTITYID",
nullable = false)
private Integer myEntityID;
//... other column mappings
public Integer getMyEntityID() {
return myEntityID;
}
public void setMyEntityID(Integer myEntityID) {
this. myEntityID = myEntityID;
}
//... other getters & setters
}