2011-09-11 116 views
3

予有需要的數據庫模式之間進行動態切換的彈簧+休眠/ Flex應用程序。爲了實現這一點,我在this文章後面實現了AbstractRoutingDataSource。不幸的是它不起作用。它實際上在默認架構(logical_public)中執行SQL。任何幫助將不勝感激。謝謝。彈簧+的SessionFactory + AbstractRoutingDataSource

這裏是我的設置:

的applicationContext.xml包含兩個數據源。每個數據源使用不同的登錄角色連接到數據庫。路由數據源通過使用String鍵選擇正確的數據源。 SchemaConstants類包含幾個公共靜態最終字段。

<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; 
    } 
} 

Globals類:用來存儲和查找數據源鍵。

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。我還沒有研究過有關此事的任何信息,但如果有人能提供信息,我們也將非常感謝。

+0

那你有沒有管理有一個JTA事務封裝既節省?怎麼樣? – Vedran

回答

7

很明顯,當調用AbstractRoutingDataSource.getConnection()時,即當創建了事務綁定休眠Session時,實際發生對特定DataSource的選擇。在你的情況下,當你輸入@Transactional方法時會發生這種情況。

因此,你不能在事務內切換方案。您必須針對不同的計劃執行單獨的交易。要在同一方法內執行多個事務,可以使用編程事務管理(TransactionTemplate)而不是@Transactional