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 Tue, 15 Jan 2008 17:41:24 GMT
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