ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Fearghal O Maolcatha" <fearghal.omaolca...@gmail.com>
Subject Re: Changing datasource at runtime
Date Wed, 16 Jan 2008 21:21:19 GMT
Thanks for the feedback - creating a new Spring context could be a good
option as well.

On 16/01/2008, Christopher Lamey <clamey@localmatters.com> wrote:
>
> 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