3

我有一个使用 Spring 3.1.1 的 Web 应用程序。我们有一个使用 JdbcTemplate 的 genericDao。Datasource 在 GenericDaoImpl 中是这样注入的。

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);
}

}

这是一个简单的 DAO。

@Repository
public class ElementDaoImpl extends GenericDaoImpl<Element> implements ElementDao {

    private static ParameterizedRowMapper<Element> mapper = new ParameterizedRowMapper<Element>() {...};

    public List<Element> findChildren(int id) {
        sql = "SELECT....";
        return findAll(sql, mapper, new Object[] {id});
    }

}

目前,凭借独特的数据源,它运行良好。applicationContext 配置有注解。

<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"/>

现在我必须集成一个仍然使用genericDao的新DAO,但在另一个数据库(所以另一个数据源)上工作。

我在服务中使用@Transactionnal。我在 spring 文档上读到,我们可以给事务一个限定符,以便选择好的事务管理器。

所以,我创建了一个新的数据源,一个新的事务管理器......

<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"/>

在我的新服务上,我已将值添加到 @Transactionnal 注释中:

 @Transactionnal("txSecond")

重新开始,我有 4 个类来管理新数据库:服务接口、使用 @Transactionnal("txSecond") 的服务实现、DAO 接口、基于 genericDao 的 DAO 实现,在注入的数据源上创建了一个 JdbcTemplate 对象。

我创建了一个 Junit 测试,但暂时我阻止了一个异常: NoSuchBeanDefinitionException:没有定义 javax.sql.DataSource 类型的唯一 bean。预期单个匹配 bean,但找到 2 个(firstDs,SecondDs)。

我认为 pb 是 genericDao 但不确定。

如何管理?

谢谢你。

4

4 回答 4

3

在配置文件中的每个 bean 上手动设置数据源

<bean id="elementDao" class="ElementDaoImpl" autowire="byName">
   <property name="datasource" ref="datasource2">
</bean>

另一个解决方案:使用“别名” http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-java-bean-混叠

于 2012-11-12T14:32:33.757 回答
0

问题是在自动装配数据源时,您没有指定任何限定符。

 @Autowired


public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);

}

因此,如果您需要将两个数据源放在同一个类中,请使用两个不同的 setter 注入配置它们,并在每种情况下提供适当的限定符。

于 2012-11-13T15:38:56.277 回答
0

有比添加限定符更优雅的解决方案。

Spring:如何从依赖注入中隐藏 bean?

自动装配两个实现相同接口的 bean - 如何将默认 bean 设置为自动装配?

于 2013-10-16T09:14:22.017 回答
0

默认情况下,自动装配注解按 bean 类型映射,因此当配置 xml 中存在多个相同类型的 bean 时,必须使用qualifier("bean id")来让 Spring 容器知道要装配哪个 bean。

于 2013-09-30T20:12:58.073 回答