OK - got it.
So I think that'll work.
You could also create a new Spring context when the DS changes and not do
the routing.
Or if you don't need caching, then you could just change the DS and use a
single sqlmapclient.
On 1/15/08 2:25 PM, "Fearghal O Maolcatha" <[EMAIL PROTECTED]>
wrote:
> My logic (flawed as it might be) was that I needed a wrapper for the
> SqlMapClient. Each DAO would be injected with a wrapper
> (RoutingSqlMapClient) for a SqlMapClient. When the datasource changes, I
> construct a new SqlMapClient and update the reference in RoutingSqlMapClient
> with the new SqlMapClient. The DAO is unaware of any changes to the
> underlying datasource.
>
>
> On 15/01/2008, Christopher Lamey <[EMAIL PROTECTED]> wrote:
>>
>> 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.
>>>>
>>>>
>>
>>