简体   繁体   English

Spring TransactionManager 和注释的 3 个问题

[英]Spring 3 problems with TransactionManager and annotations

I'm trying to setup a TransactionManager in my Web Application (powered by Spring MVC 3), as I need to have one method of a component annotated as @Transactional .我正在尝试在我的 Web 应用程序(由 Spring MVC 3 提供支持)中设置一个TransactionManager ,因为我需要一个组件的方法注释为@Transactional

This is my situation:这是我的情况:

  • web.xml : load 2 xml files for the Spring ContextLoaderListener ( applicationContext.xml and database.xml ) web.xml : load 2 xml files for the Spring ContextLoaderListener ( applicationContext.xml and database.xml )
  • applicationContext.xml: contains some beans which I can't define via annotation, plus the tags for annotation, plus the usual context:annotation-config and context:component-scan (this component-scan includes the package that contains the @Transactional method) applicationContext.xml:包含一些我无法通过注释定义的bean,加上注释的标签,加上通常的 context:annotation-config 和 context:component-scan (这个组件扫描包括 package 包含@Transactional方法)
  • database.xml : contains the datasource (I'm using BasicDataSource from commons-dbcp), the transaction manager definition and tx:annotation-driven. database.xml :包含数据源(我使用来自 commons-dbcp 的BasicDataSource )、事务管理器定义和 tx:annotation-driven。

I've got a @Component (DeleteComponent ) which has an interface and an implementation ( DeleteComponentImpl ).我有一个@Component (DeleteComponent ),它有一个接口和一个实现 ( DeleteComponentImpl )。 The implementation class is annotated with @Component and has one public method annotated with @Transactional (I annotated the concrete class and not the interface, as Spring documentation states).实现 class 用@Component注释,并且有一个用@Transactional注释的公共方法(我注释了具体的 class 而不是接口,如 Spring 文档所述)。 For @Transactional I didn't put any arguments, as defaults are fine.对于@Transactional ,我没有放任何 arguments,因为默认值很好。 This class has some DAOs (annotated with @Repository ) being injected via @Autowired .这个 class 有一些通过@Autowired注入的 DAO(用@Repository注释)。 I'm using only plain JDBC (no Hibernate or other ORM).我只使用普通的 JDBC (没有 Hibernate 或其他 ORM)。 This @Component is injected into a @Controller (which is defined in spring- servlet.xml ).这个@Component被注入到@Controller (在spring- servlet.xml中定义)。

If the method annotated as @Transactional throws an exception (unchecked, as RuntimeException ), however, nothing is rolled back.但是,如果注释为@Transactional的方法抛出异常(未经检查,如RuntimeException ),则不会回滚任何内容。 The database retains the changes did before the exception.数据库保留异常之前所做的更改。 I'm using Jetty web server for testing locally my application.我正在使用 Jetty web 服务器在本地测试我的应用程序。 The thing I noticed is actually that seems like no transaction manager is being set up.我注意到的事情实际上似乎没有设置事务管理器。 Actually, my transaction manager is named transactionManager .实际上,我的事务管理器名为transactionManager The xml line to set up the annotation-driven transaction is设置注释驱动事务的 xml 行是

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

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

If I change it to use a non-existing bean name like如果我将其更改为使用不存在的 bean 名称,例如

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

The application still deploys correctly and doesn't complain.该应用程序仍然正确部署并且没有抱怨。

Any tips on what should I check to make it working?关于我应该检查什么以使其正常工作的任何提示?

Thanks.谢谢。

I solved by using @Transactional(rollbackFor = RuntimeException.class) and switching from a BasicDataSource to a ComboPooled that's present in c3p0 library.我通过使用@Transactional(rollbackFor = RuntimeException.class)并从BasicDataSource切换到 c3p0 库中存在的ComboPooled来解决。 Thanks for the suggestions though.不过感谢您的建议。

To get rollback when an exception is thrown add this:要在抛出异常时回滚,请添加:

@Transactional(rollbackFor=Exception.class)

You will also need to set up the transactionManger bean (here is mine, using hibernate):您还需要设置 transactionManger bean(这是我的,使用 hibernate):

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

I found thistutorial informative.我发现本教程内容丰富。

I believe that @Autowired and @Resource aren't scanned by Spring on a @Component .我相信@Autowired@Resource不会被@Component上的 Spring 扫描。 Try to use a ContextHolder class to get the context and the DAO尝试使用ContextHolder class 来获取上下文和 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;
    }
}

and call your dao with:并通过以下方式调用您的 dao:

ContextHolder.getApplicationContext().getBean("MyDAO");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM