I'm confused - why do you need the routing if you only need to support
access to one db at a time?
On 1/15/08 10:41 AM, "Fearghal O Maolcatha" <[EMAIL PROTECTED]>
wrote:
> Hi Chris,
>
> Thanks for the response. I'd actually seen your solution previously. I was
> using it as a starting point for what I was trying to do, specifically the
> RoutingSqlMapClient class. I've modified it slightly for my purposes to just
> contain a reference to one SqlMapClient. We only need to support access to
> one database at a time.The bean 'projSqlMapClient' is injected with a known
> database at startup. I've included some test code, where I construct a new
> DataSource and update the projSqlMapClient bean with the newly constructed
> SqlMapClient. It seems to work for the simple test case I've written but
> there might be something I've overlooked. I'd appreciate any feedback you
> might have on this approach.
>
> Thanks,
> Fearghal.
>
>
>
> public class TestSpringContext {
>
> public static void main(String[] args) throws Exception {
> ContextManager.getContext();
>
> // Create DataSource for the new database
> BasicDataSource projectDS = new BasicDataSource();
> projectDS.setPassword("NsdSa123");
> projectDS.setDriverClassName("
> com.microsoft.sqlserver.jdbc.SQLServerDriver");
> projectDS.setUrl
> ("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=NSD_DB2");
> projectDS.setUsername("Sa");
>
> // Create a SqlMapClient for the new DataSource
> SqlMapClientFactoryBean factoryBean = new SqlMapClientFactoryBean();
> Resource resource = new ClassPathResource("config/sqlmaps/sql-
> map-config.xml");
> factoryBean.setConfigLocation(resource);
> factoryBean.setDataSource(projectDS);
> try {
> factoryBean.afterPropertiesSet();
> } catch (Exception e) {
> throw new RuntimeException(e);
> }
>
>
> ExtendedSqlMapClient client =
> (ExtendedSqlMapClient)factoryBean.getObject();
>
>
> RoutingSqlMapClient routingClientMap =
> (RoutingSqlMapClient)ContextManager.getContext().getBean("projSqlMapClient");
> // update reference to SqlMapClient
> routingClientMap.setTargetSqlMapClient(client);
>
> // Update the TransactionManager to use the new DataSource
> DataSourceTransactionManager myTransMgr =
> (DataSourceTransactionManager) ContextManager.getContext
> ().getBean("transactionManager");
> myTransMgr.setDataSource(projectDS);
> myTransMgr.afterPropertiesSet();
>
> // Test that it now accesses the correct database and that
> transactions are
> // still working
> sites = siteOps.getSites(requestParams, null);
> try {
> site.setId(null);
> siteOps.saveSite(null, site);
> }
> catch (Exception e) {
> e.printStackTrace();
> }
> }
> }
>
>
> Context File:
> <beans>
>
> <!-- ========================= RESOURCE DEFINITIONS
> ========================= -->
>
> <bean id="dataSource"
> class="org.apache.commons.dbcp.BasicDataSource"
> destroy-method="close">
> <property name="driverClassName" value="${dbunit.driverClass}" />
> <property name="url" value="${dbunit.connectionUrl}" />
> <property name="username" value="${dbunit.username}" />
> <property name="password" value="${dbunit.password}" />
> </bean>
>
> <!-- Transaction manager for a single JDBC DataSource -->
> <bean id="transactionManager"
> class="
> org.springframework.jdbc.datasource.DataSourceTransactionManager">
> <property name="dataSource" ref="dataSource" />
> </bean>
>
> <!-- SqlMap setup for iBATIS Database Layer -->
> <bean id="sqlMapClient"
> class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
> <property name="configLocation"
> value="config/sqlmaps/sql-map-config.xml" />
> <property name="dataSource" ref="dataSource" />
> </bean>
>
> <bean id="projSqlMapClient"
> class="com.foo.persistence.dao.RoutingSqlMapClient">
> <property name="targetSqlMapClient" ref="sqlMapClient"/>
> </bean>
>
> <!-- ========================= DAO DEFINITIONS: IBATIS IMPLEMENTATIONS
> ========================= -->
>
> <bean id="customerDao"
> class="com.foo.persistence.dao.CustomerDaoImpl">
> <property name="sqlMapClient" ref="sqlMapClient" />
> </bean>
>
> <bean id="projectDao"
> class="com.foo.persistence.dao.ProjectDaoImpl">
> <property name="sqlMapClient" ref="sqlMapClient" />
> </bean>
>
> <bean id="siteDao"
> class="com.foo.persistence.dao.SiteDaoImpl">
> <property name="sqlMapClient" ref="projSqlMapClient" />
> </bean>
>
> </beans>
>
> On 15/01/2008, Christopher Lamey <[EMAIL PROTECTED]> wrote:
>>
>> Spring isn't good at dynamic DataSource stuff, especially new ones that
>> get
>> created after the Spring context is instantiated.
>>
>> This item on the FAQ details the solution I came up with for my stuff:
>>
>>
>> http://opensource.atlassian.com/confluence/oss/pages/viewpage.action?pageId=
>> 12583003
>>
>> There aren't any issues with caching, but the DataSources must be known at
>> Spring creation time which I don't think will work for you.
>>
>> I've been thinking up different ways of doing this so I don't have to rely
>> on code changes to get a new datasource running, but I haven't spent much
>> time on it. It would be much easier to do without Spring, you could just
>> use iBATIS directly and create sqlmapclients with a properties object to
>> configure it. But Spring offers a lot of nice stuff which I don't want to
>> get rid of...
>>
>> Cheers,
>> Chris
>>
>> On 1/15/08 8:57 AM, "Fearghal O Maolcatha" <[EMAIL PROTECTED]>
>> wrote:
>>
>>> Hi,
>>>
>>> Our project is currently using Ibatis and the Ibatis DAOs. We plan to
>>> migrate the Ibatis DAOs to Spring DAOs, which seems straightforward
>> enough.
>>> However we have a new requirement that will necessitate the changing of
>> the
>>> datasource at runtime. Our application has the notion of projects, with
>> each
>>> new project created by the user requiring a new database (same DB schema
>> for
>>> all projects). Any new work within the project will be saved to the
>> newly
>>> created database. The user can close a project and open an existing one,
>>> which would require the datasource to be changed. I've had a look at a
>>> previous thread
>>> http://www.mail-archive.com/[email protected]/msg08475.htmlwhich
>>> addresses a similar issue but the suggested implementation (wrapping the
>>> datasource being injected into the SqlMapClient) would have implications
>> for
>>> the Ibatis cache from what I've read previously. We currently don't use
>> the
>>> Ibatis cache but might have to for performance reasons in the future.
>>>
>>> Any suggestions on how to proceed with this would be welcome.
>>>
>>> Regards,
>>> Fearghal.
>>
>>