Dynamic data routing

Sorry for my bad english. I wrote an implementation for AbstractRoutingDataSource:

public class DatabaseRoutingDataSource extends AbstractRoutingDataSource{

    @Override
    protected Object determineCurrentLookupKey() {      
        return DatabaseContextHolder.getDatabaseType();
    }

}

      

And I created a new class to switch between databases:

public class DatabaseContextHolder {

    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();

    public static void setDatabaseType(DatabaseType databaseType) {
        contextHolder.set(databaseType);
    }

    public static DatabaseType getDatabaseType() {
        return (DatabaseType) contextHolder.get();
    }

    public static void clearDatabaseType() {
        contextHolder.remove();
    }
}

      

where DatabaseType:

public enum DatabaseType {
    MAIN,
    BACKUP
}

      

in beans.xml:

<bean id="mainDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/jdbc/DBMIDS"/>
</bean>
<bean id="backupDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/jdbc/DBMIDS2"/>
</bean>
<bean id="dataSource" class="DatabaseRoutingDataSource">
    <property name="targetDataSources">
        <map key-type="DatabaseType">
            <entry key="MAIN" value-ref="mainDataSource"/>
            <entry key="BACKUP" value-ref="backupDataSource"/>
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="mainDataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<bean id="databaseTarget" class="DatabaseBean">
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="database" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="target" ref="databaseTarget"/>
    <property name="proxyInterfaces">
        <value>Database</value>
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="*">PROPAGATION_REQUIRED,-MyException</prop>
        </props>
    </property>
</bean>

      

Now when I try to change the datasource in my DAO:

public class DatabaseBean extends JdbcDaoSupport implements Database
    public void myMethod() {
       DatabaseContextHolder.setDatabaseType(DatabaseType.MAIN);
       getJdbcTemplate().execute("INSERT INTO test(test) VALUES('test')");      
       DatabaseContextHolder.setDatabaseType(DatabaseType.BACKUP);
       getJdbcTemplate().execute("INSERT INTO test(test) VALUES('test')");        
}

      

defineCurrentLookupKey () called once, when getJdbcTemplate () is first executed and the data source is not switched.

+1


source to share


2 answers


Part of Spring transaction management for JDBC transactions is to bind the connection to the thread when the transaction starts. Until the transaction ends and the connection is connected, each save operation to the same data source will use the same connection. Since you are using one data source to mask the other two, you only get one connection. If you explicitly used two separate data sources, each will be treated as a separate resource, and a separate connection will be started and bound to the thread for each. See "Resource Synchronization with Transactions" in the Reference Manual, at least for a hint of what happens under the hood when using transactions with JdbcDaoSupport and JdbcTemplate.



+5


source


You must call DatabaseContextHolder.setDatabaseType (DatabaseType.MAIN) before calling the method. Hibernate looks for a connection after starting a transaction. In your case, the transaction starts before DatabaseContextHolder.setDatabaseType (DatabaseType.MAIN) has been started. And once the transaction has started, the schema cannot be changed. Your implementation is correct trying to set the DatabaseType before calling the method, that is, before starting the transaction.



+1


source







All Articles