2011-09-11 117 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