J'ai une application Spring + Hibernate/Flex qui doit basculer dynamiquement entre les schémas de base de données. Pour ce faire, j'ai implémenté un article AbstractRoutingDataSource suivant this. Malheureusement, cela ne fonctionne pas. Il exécute en fait le SQL dans le schéma par défaut (logical_public). Toute aide serait grandement appréciée. Merci.Spring + Hibernate SessionFactory + AbstractRoutingDataSource
Voici ma configuration:
applicationContext.xml contient les deux sources de données. Chaque source de données se connecte à la base de données avec un rôle de connexion différent. La source de données de routage sélectionne la bonne source de données en utilisant une clé String. La classe SchemaConstants contient deux champs publics statiques finals.
<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>
mise en œuvre de RoutingDataSource: Pas grand-chose à ajouter ici.
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;
}
}
La classe Globals: Utilisé pour stocker et rechercher la clé de source de données.
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();
}
}
Code d'essai: tente d'insérer quelques enregistrements, chacun dans différents schémas (et tables différentes)
@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);
}
Une question secondaire. Quelle est la bonne façon de garder mon intégrité des données dans une telle situation? J'ai annoté la méthode avec l'attribut @Transactional mais je suis loin d'être certain que cela fonctionnerait si facilement. Le gestionnaire de transaction que j'utilise est de type org.springframework.orm.hibernate3.HibernateTransactionManager. Je n'ai pas encore fait de recherches sur le sujet, mais si quelqu'un peut fournir des informations, cela sera grandement apprécié.
Alors avez-vous réussi à faire encapsuler une transaction JTA à la fois les sauvegardes? Comment? – Vedran