Para utilização de um banco write e outro read-only em uma aplicação com Spring, siga as instruções abaixo:

1. Crie uma classe que contenha os tipos que farão distinção entre os bancos de escrita e leitura.

Por exemplo:

 public enum DatabaseType {
    READ_ONLY,
    WRITE
 }

2. Crie uma classe que armazenará o tipo no context da thread em execução.

 public class DatabaseContextHolder {
    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();


    public static void setDatabaseType(DatabaseType databaseType) {
        if (databaseType == null)
            databaseType = DatabaseType.WRITE; // default to write database
        contextHolder.set(databaseType);
    }


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


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

3. Criar um DataSource específico que fará o roteamento baseado no tipo definido.

 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

 public class DatabaseRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getDatabaseType();
    }
 }

4. Criar uma annotation para definir o tipo desejado.

Vc pode criar uma onde se escolha o tipo ou uma que seja read-only e aplique onde for necessário. Vou colocar aqui o último caso:

 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
 public @interface ReadOnlyDatabase {
 }

5. Criar um interceptor para captar o uso da annotation.

 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;


 public class DatabaseTypeAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Annotation[] annotations = methodInvocation.getMethod().getAnnotations();
        DatabaseType databaseType = DatabaseType.WRITE;
        for (Annotation annotation : annotations) {
            if (annotation instanceof Entity)
                databaseType = DatabaseType.READ_ONLY;
        }
        DatabaseContextHolder.setDatabaseType(databaseType);
        return methodInvocation.proceed();
    }
 }

6. Feito isso é só configurar no application-context.xml.

<bean id="databaseRoutingDataSource" class="pacote.DatabaseRoutingDataSource">
    <property name="targetDataSources">
        <map key-type="pacote.DatabaseType">
            <entry key="WRITE" value-ref="writeDataSource"/>
            <entry key="READ_ONLY" value-ref="readOnlyDataSource"/>
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="writeDataSource"/>
</bean>

Note que no "sessionFactory" vc deve definir o datasource acima.

Defina o interceptor:

<bean id="databaseTypeAdvice" class="pacote.DatabaseTypeAdvice"/>

 

E no "applicationTxProxyTemplate" inclua a seguinte propriedade que referencie o interceptor:

<property name="preInterceptors">
    <list>
        <ref local="dataSourceTypeAdvice"/>
    </list>
</property>