2

我正在尝试TransactionManager在我的 Web 应用程序(由 Spring MVC 3 提供支持)中设置一个,因为我需要将一个组件的方法注释为@Transactional.

这是我的情况:

  • web.xmlContextLoaderListener: 为 Spring (applicationContext.xmldatabase.xml)加载 2 个 xml 文件
  • applicationContext.xml:包含一些我无法通过注释定义的bean,加上注释的标签,加上通常的 context:annotation-config 和 context:component-scan (这个组件扫描包括包含该@Transactional方法的包)
  • database.xml: 包含数据源(我BasicDataSource从 commons-dbcp 使用)、事务管理器定义和 tx:annotation-driven。

我有一个@Component (DeleteComponent),它有一个接口和一个实现 ( DeleteComponentImpl)。实现类被注释@Component并有一个公共方法被注释@Transactional(我注释了具体类而不是接口,如 Spring 文档所述)。因为@Transactional我没有提出任何论据,因为默认值很好。这个类有一些@Repository通过@Autowired. 我只使用普通的 JDBC(没有 Hibernate 或其他 ORM)。这@Component被注入到@Controller(在 spring- 中定义servlet.xml)中。

但是,如果注释为 as 的方法@Transactional抛出异常(未选中, as RuntimeException),则不会回滚任何内容。数据库保留异常之前所做的更改。我正在使用 Jetty Web 服务器在本地测试我的应用程序。我注意到的事情实际上似乎没有设置事务管理器。实际上,我的事务管理器名为transactionManager. 设置注释驱动事务的 xml 行是

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

如果我将其更改为使用不存在的 bean 名称,例如

<tx:annotation-driven transaction-manager="fake"/>

该应用程序仍然正确部署并且没有抱怨。

关于我应该检查什么以使其正常工作的任何提示?

谢谢。

4

3 回答 3

2

我通过使用@Transactional(rollbackFor = RuntimeException.class)并从 a 切换BasicDataSourceComboPooledc3p0 库中存在的 a 来解决。不过感谢您的建议。

于 2011-07-19T12:21:08.533 回答
1

要在抛出异常时回滚,请添加:

@Transactional(rollbackFor=Exception.class)

您还需要设置 transactionManger bean(这是我的,使用休眠):

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
                p:sessionFactory-ref="sessionFactory" />

我发现本教程内容丰富。

于 2011-07-15T09:02:00.020 回答
-2

我相信这一点,@Autowired并且@ResourceSpring 不会在@Component. 尝试使用一个ContextHolder类来获取上下文和 DAO

@Component
public class ContextHolder implements ApplicationContextAware {

    /** 
     * Spring context which will directly be injected by Spring itself
     */
    private static ApplicationContext context = null;

    /**
     * Overridden method of ApplicationContextAware, which will automatically be called by the container
     */
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context = context;
    }

    /**

    /**
     * Static method used to get the context
     */
    public static ApplicationContext getApplicationContext() {
        return context;
    }
}

并通过以下方式调用您的 dao:

ContextHolder.getApplicationContext().getBean("MyDAO");
于 2011-07-15T13:25:50.413 回答