ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Lamey <cla...@localmatters.com>
Subject Re: Changing datasource at runtime
Date Wed, 16 Jan 2008 17:49:13 GMT
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" <fearghal.omaolcatha@gmail.com>
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 <clamey@localmatters.com> 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" <fearghal.omaolcatha@gmail.com
>>> 
>> 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 <clamey@localmatters.com> 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" <
>> fearghal.omaolcatha@gmail.com>
>>>> 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/user-java@ibatis.apache.org/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.
>>>> 
>>>> 
>> 
>> 


Mime
View raw message