21

私は今日これをたくさん研究していて、私がやりたいことは不可能かもしれないと思い始めているので、私はあなたに助けを求めています。

私はJavaでRESTfulサービスプラットフォームを構築しており、永続層としてSpring Data 3.1.2 + JPAを使用しています(ここに記載されています)。私のデータモデルオブジェクトはすべて、SpringJpaRepositoryインターフェイスを拡張するインターフェイスとして実装されています。この例に示すように、すべてが接続され、単一のデータソースでうまく機能しています(示されているデータソースはDerbyですが、これは開発目的のみです。本番環境ではOracleを使用します)。

<jpa:repositories base-package="com.my.cool.package.repository"/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
  </property>
  <property name="packagesToScan" value="com.my.cool.package" />
  <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>

<bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="emf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
  <property name="url" value="jdbc:derby:derbyDB" />
  <property name="username" value="dev" />
  <property name="password" value="notARealPassword" />
</bean>

<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
  <property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
</bean>

問題は、このアプリケーションがいくつかの(Oracle)データベースに接続する必要があることです。各着信要求に含まれる資格情報には、その要求を満たすためにどのデータベースに移動するかをアプリケーションに指示するフィールドが含まれます。各データベースのスキーマは同じであるため、データベースごとに個別のリポジトリインターフェイスは必要ありません。

かなりの量のグーグルの後、これが一般的なシナリオであることは明らかです。ウィットに:

そして、これが(元?)Spring開発者によるブログ投稿です。これは実際には目前のトピックとは関係ありませんが、誰かがコメントでそれを取り上げ、作者はいくつかの情報で応答します。

http://blog.springsource.org/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/#comment-198835

浮上しているように見えるテーマは、この問題を解決する方法は、複数のEntityManagerFactoriesを定義し、それぞれを次のように適切なリポジトリに接続することです。

<jpa:repositories base-package="com.my.cool.package.repository1" entity-manager-factory-ref="firstEntityManagerFactory" />
<jpa:repositories base-package="com.my.cool.package.repository2" entity-manager-factory-ref="secondEntityManagerFactory" />

ただし、前述したように、すべてのデータソースでリポジトリを再利用したいので、このアプローチはうまくいかないようです。

リクエストから関連情報を取得し、それを使用して使用するデータソース(またはEntityManagerFactory)を決定するロジックをコードに含める方法はないことを私は知っています。私が苦労しているのは、そのdatasource / EntityManagerFactoryへのハンドルを取得し、それをリポジトリオブジェクトに「注入」する方法です。何か案は?

4

1 に答える 1

24

DataSourceさまざまなesをマルチテナントのような方法で実際に使用している場合(基本的には、にリクエストを割り当て、リクエストDataSource全体でそれを維持する)、を確認する必要がありますAbstractRoutingDataSource。これは基本的にMap、 esを保持する方法と、最終的にDataSource使用されるを検索するために使用されるキーを返すコールバックメソッドを提供します。DataSourceこのメソッドの実装は通常、スレッドにバインドされたキーを検索して返します(または、それをDataSourceマップキーにマップします)。そもそも、いくつかのWebコンポーネントがそのキーをスレッドにバインドしていることを確認する必要があります。

これが適切に行われている場合、Spring構成は、のサブクラス用のBeanをセットアップし、AbstractRoutingDataSourceそのマップをパイプ処理DataSourcesするだけです。SpringDataJPAのセットアップはデフォルトの方法のままです。はEntityManagerFactoryBeanを参照し、要素AbstractRoutingDataSourceは1つ<jpa:repositories />だけです。

于 2012-09-27T22:13:58.757 に答える