データベーススキーマ間で動的に切り替える必要があるSpring + Hibernate/Flexアプリケーションがあります。これを達成するために、thisの記事に続いてAbstractRoutingDataSourceを実装しました。残念ながら、それは動作しません。実際には、デフォルトのスキーマ(logical_public)でSQLが実行されます。どんな助けでも大歓迎です。ありがとう。ここでSpring + Hibernate SessionFactory + AbstractRoutingDataSource
は私の設定です:
applicationContext.xmlをは、二つのデータソースが含まれています。各データソースは、異なるログインロールを持つデータベースに接続します。ルーティングデータソースは、Stringキーを使用して適切なデータソースを選択します。 SchemaConstantsクラスには、public static finalフィールドが含まれています。
<bean id="parentDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver"/>
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/mystore"/>
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="1"/>
<property name="maxPoolSize" value="15"/>
<property name="maxStatementsPerConnection" value="100"/>
<property name="automaticTestTable" value="c3p0_test_table"/>
<property name="numHelperThreads" value = "20"/>
</bean>
<bean id="publicDS" parent="parentDataSource">
<property name="user" value="postgres"/>
<property name="password" value="password"/>
</bean>
<bean id="tempSchemaDS" parent="parentDataSource">
<property name="user" value="temp_role"/>
<property name="password" value="tmppsw"/>
</bean>
<bean id="routingDS" class="flex.RoutingDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="flex.SchemaConstants.LOGICAL_PUBLIC" value-ref="publicDS"/>
<entry key="flex.SchemaConstants.TEMP_SCHEMA" value-ref="tempSchemaDS"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="publicDS"/>
</bean>
RoutingDataSource実装:ここで追加するために多くの何もありません。
public class RoutingDataSource extends AbstractRoutingDataSource
{
@Override
protected Object determineCurrentLookupKey()
{
return Globals.getSchema();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException
{
// TODO Auto-generated method stub
return null;
}
}
グローバルクラス:保存し、データソースのキーをルックアップするために使用します。
public class Globals
{
private static final ThreadLocal<String> schemaHolder
= new ThreadLocal<String>();
public static void setSchema(String schema)
{
schemaHolder.set(schema);
}
public static String getSchema()
{
return schemaHolder.get();
}
public static void clearCustomerType()
{
schemaHolder.remove();
}
}
テストコード:異なるスキーマ(及び異なるテーブル)内の各レコードのカップルを挿入しようと
@RemotingInclude
@Transactional
public void test()
{
Globals.setSchema(SchemaConstants.TEMP_SCHEMA);
SomeDataOther someOtherData = new SomeDataOther();
someOtherData.setName("Jorjinio");
this.sessionFactory.getCurrentSession().save(someOtherData);
Globals.setSchema(SchemaConstants.LOGICAL_PUBLIC);
SomeData someData = new SomeData();
someData.setFirstName("Hulio");
someData.setLastName("Julio");
this.sessionFactory.getCurrentSession().save(someData);
}
二質問。このような状況でデータの整合性を保つ正しい方法は何ですか?私は@Transactional属性でメソッドに注釈を付けましたが、これは簡単に機能するとは確信していません。私が使用しているtransactionManagerはorg.springframework.orm.hibernate3.HibernateTransactionManager型のものです。私はまだ問題について何も研究していないが、もし誰かが情報を提供できるなら、それは非常に高く評価されるだろう。
JTAトランザクションで両方のセーブをカプセル化することができましたか?どうやって? – Vedran