12

次のpersistence.xmlがあり、接続URL、ユーザー、パスワードがすべてハードコーディングされているとします。

以下はHibernate3.2用です。Hibernate 3.5 ++の場合、「hibernate.connection」を「javax.persistence」に変更する必要があります。しかし、リテラル「hibernate.connection」または「javax.persistence」に関係なく、この質問をさせてください。

<persistence-unit name="obamacare" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
  <exclude-unlisted-classes>false</exclude-unlisted-classes>
  <properties>
    <property name="hibernate.archive.autodetection" value="class, hbm"/>
    <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="hibernate.connection.url" value="blah blah blah"/>
    <property name="hibernate.connection.username" value="careuser"/>
    <property name="hibernate.connection.password" value="carepass"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
    <property name="hibernate.show_sql" value="true"/>
  </properties>
  </persistence-unit>
</persistence>

ただし、URL、ユーザー、パスワードを動的に設定する必要があります。URL、ユーザー、パスワードを提供する認証サーバーが提案されています。そのため、何らかの形式のjdbc、hibernate、またはJPAを使用する無数のWebアプリケーションを個別に構成する必要はありません。表示されているテキストファイルにパスワードを保存/管理したくないというセキュリティの問題に加えて。

JPAに関する限り、これらのJPAプロパティを動的に設定するにはどうすればよいですか?私は2つの答えを求めています:

  1. JPAベンダーに依存しないソリューション(toplink、eclipselink、hibernateなど)の場合-これらの3つのプロパティを動的に設定できるJPA機能はありますか?

  2. 私が完全にHibernateに依存することを許可されている場合、可能なJPAのみの手段に加えて、Springフレームワーク(いたるところに触手がある巨大な怪物のように見える)を伴わずにこれを達成する方法はありますか?

JNDIに2セント/クイッド/ルピーを投入し、それを使用してpersistence.xmlプロパティの機能を置き換える方法を教えていただければ幸いです。しかし、それは質問の優先順位ではありません。

4

2 に答える 2

7

EntityManagerFactory をどのようにブートストラップするかによって異なります。仕様で定義された 2 つのメソッドを使用すると、値の java.util.Map を渡すことができます。これらの値は、persistence-unit で定義された値よりも優先されると想定されています。

通常、ブートストラップ プロセスはアプリによって制御されるため、「SE アプローチ」では問題ありませんjavax.persistence.Persistence#createEntityManagerFactory(String puName, Map config。他の何か(エヘム、Spring)がEMFを「管理」している場合、ここで問題が発生する可能性があります...

「EE アプローチ」では、優れたグローバル アプローチを認識していません。この値のマップはまだブートストラップに存在しますが、問題は EE コンテナーがこのメソッドを呼び出していることです。

どちらの場合でも機能する Hibernate 固有のアプローチの 1 つは、構成変数の置換を使用することです。したがって、persistence-unit では、ユーザー名またはパスワードを使用して定義し${some.key}、Hibernate がそれらを置き換えます。これが実際に機能するかどうかは、これらの値を最終的にどのように設定するかによって異なります。Hibernate はsome.key、これが機能するために名前が付けられた構成値にアクセスする必要があります...

さらに別の「グローバル アプローチ」... EMF をブートストラップする「EE アプローチ」は、コンテナーが javax.persistence.spi.PersistenceProvider をインスタンス化し、その javax.persistence.spi.PersistenceProvider#createContainerEntityManagerFactory を呼び出すことです。createContainerEntityManagerFactory には、ここで興味深い署名があります。基本的に、解析された永続ユニットとその他のもののオブジェクト表現である javax.persistence.spi.PersistenceUnitInfo が渡されます。オプションは、このアプローチを使用してブートストラップし、自分で構築した javax.persistence.spi.PersistenceUnitInfo のインスタンスを渡すことです。javax.persistence.spi.PersistenceProvider はインターフェースです。インスタンス化するには、使用するプロバイダーとその実装への FQN を知る必要があります。

具体的には、JDBC 接続の作成/プーリングについて質問しています。具体的には、追加のオプションがあります。「資格情報サービス」に DataSource を作成させ、JPA プロバイダーは単にその DataSource を使用することができます。すべての JPA プロバイダーは、JNDI ルックアップによる DataSource の検索をサポートしています。「EE ブートストラップ」では、プロバイダーに DataSource を渡して、PersistenceUnitInfo#getJtaDataSource および/または PersistenceUnitInfo#getNonJtaDataSource を介して使用することもできます。Hibernate は、通常の DataSource JNDI 名設定の代わりに、代わりに DataSource インスタンスを受け入れます。(奇妙な理由で) DataSource を使用したくない場合、Hibernate 固有の代替手段は、Hibernate の ConnectionProvider コントラクトを自分で実装することです。これは、Hibernate が必要なときに JDBC 接続を取得および解放するために使用するコントラクト (インターフェイス) です。

たくさんのオプション:)

于 2012-07-27T23:11:31.740 に答える
3

2 番目の質問については、Hibernate のみのソリューションを提供できます。

package dev.stackoverflow;

import java.util.Properties;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class DynamicHibernateSessionFactory {
    public Session setProperties(final String provider,
                                 final Boolean excludeUnlisted,
                                 final Properties properties) {
        properties.setProperty("provider", provider);
        properties.setProperty("exclude-unlisted-classes", excludeUnlisted.toString());
        Configuration configuration = new Configuration();
        configuration.setProperties(properties);
        SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
        return sessionFactory.openSession();
    }
}
于 2012-07-27T21:09:46.703 に答える