Announcement Announcement Module
Collapse
No announcement yet.
JdbcTemplate / GenericDao / @Transactionnal / Multiple DataSource Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JdbcTemplate / GenericDao / @Transactionnal / Multiple DataSource

    Hello, i have a genericDao where datasource is injected.

    Code:
    public class GenericDaoImpl<T extends Serializable> implements GenericDao<T> {
    
    protected Class<T> entityClass;
    
    protected JdbcTemplate jdbcTemplate;
    
    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
    
    ....
    
    @Override
    public List<T> findAll(String sql, ParameterizedRowMapper<T> mapper, Object... args) {
        return jdbcTemplate.query(sql, mapper, args);
    }
    
    }
    All my DAOs extends from this genericDaoImpl.

    In my applicationContext, all is working fine until i have only one datasource. Here my applicationContext.xml :

    Code:
    <context:annotation-config/>
    <context:component-scan base-package=".....persistence, ....service" />
    
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/...."/>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
    Unfortunatly, now i have to manage mutliple database access.
    So, i change configuration based on spring documentation for multiple transaction manager.

    I created a new datasource, a new transaction manager...

    Code:
    <bean id="firstDS" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/...."/>
    </bean>
    
    <bean id="secondDS" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/...."/>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="firstDS"/>
    </bean>
    
    <bean id="txManagerSecond" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="secondDS"/>
        <qualifier value="txSecond"/>
    </bean>
    
    <tx:annotation-driven proxy-target-class="true"/>
    ... and added the qualifier value into @Transactionnal of my new service.

    Code:
    @Transactionnal("txSecond")

    For moment, i have just created a new Service/Dao to access to new database.
    I would like to set the qualifier value for this database, and keep classic @Transactionnal for all others DAO in order to get the default transactionmanager.

    Actualy, i have an exception : NoSuchBeanDefinitionException
    No Unique bean of type javax.sql.DataSource is defined. Expected Single matching bean but found 2 (firstDS, secondDS).

    I suppose the pb is the @Autowired into my genericDao.

    But how to solve that ? i was supposing multiple transaction manager was there in order to manage the good datasource.

    Any idea ?

    Thank you.

  • #2
    Had very simmilar problem, try to add two libraries - jta1.1.jar and cglib-nodep-2.1_3.jar to Your /lib.

    Comment


    • #3
      My mistake : i didn't understood totaly the configuration.

      The pb is really the autowired datasource. It can't determine the good datasource to inject.
      In order to working with multiple database, we have to create multiple datasource, multiple transaction manager, use qualifier in @Transactionnal. But to have a generic dao, we have to create a parent class which will have all treatment with JdbcTemplate, and some children which just inject the datasource by a setter in order to create the JdbcTemplate object (with @Resource(name="xxxDS") to inject the specific datasource).

      So in my case, i have the genericDao, genericDaoXxx1 and genericDaoXxx2. After my Dao extends from genericDaoXxx1 or genericDaoXxx2.

      I hope that will help someone else....

      Comment

      Working...
      X