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 Tue, 15 Jan 2008 20:37:30 GMT
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