实际开发环境中经常会遇到Spring框架配置事物失败或不起作用问题,而且无法直观的在代码中追根溯源。工程师们绞尽脑汁,检查各项配置参数、查看日志、反向推理等等手段去排除问题所在。本文就将出现最为频繁的常见问题总结分析:

目录


  • 目录
  • 数据库非事务支持引擎导致
  • 使用context:component-scan重复扫描导致
  • 事务配置错误
  • 代理方法必须是公共函数(public标志)


数据库非事务支持引擎导致

使用Spring框架配置事务,其最终落实还是数据库的支持,如果项目所使用数据库不支持事务配置那自然配置失败。以MySQL为例常用的数据库引擎有InnoDB和MyISAM。其中InnoDB支持事务,MyISAM不支持。所以如果当前数据库表不是InnoDB的话需要修改过来,修改语句为:alert table [表名] type = InnoDB;

使用context:component-scan重复扫描导致

在配置文件中经常看见如下代码:

<context:component-scan base-package="com.lst.*"/>

事务的植入层一般都是通过代理类,而一般情况下这个代理类是不需要扫描的。上述代码,会将com.lst下的所有文件包统统扫描一次。所以,这时候最容易出现事务配置不起作用的问题。
建议修改方式,如:

<context:component-scan base-package="com.lst.*" >
        <context:exclude-filter type="annotation"  expression="org.springframework.stereotype.Service" />
</context:component-scan>

因为我们通常会将事务层配置到Impl类中,并注解@Service注解作为代理实现类。该代码含义即为当扫描com.lst.下的所有文件包时,排除标记@Service注解代理类。这样就避免了事务不起作用问题。

事务配置错误

这类错误算是粗心或者对Spring事务配置不熟悉导致,这里我将事务基本配置写出来,可做模板参考。
1、配置事务管理器

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

2、配置事务(注解方式)

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

2、配置事务(拦截器方式)

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" read-only="false"
                rollback-for="java.lang.Exception" no-rollback-for="" />
            <tx:method name="create*" propagation="REQUIRED" read-only="false"
                rollback-for="java.lang.Exception" no-rollback-for="" />
            <tx:method name="do*" propagation="REQUIRED" read-only="false"
                rollback-for="java.lang.Exception" no-rollback-for="" />
            <tx:method name="process*" propagation="SUPPORTS" />
            <tx:method name="*" propagation="SUPPORTS" />
        </tx:attributes>
    </tx:advice>

3、引入AOP

<aop:config>
    <aop:pointcut id="transactionPointcut" expression="execution( * com.lst..service.*.*(..))" />
    <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
</aop:config>

代理方法必须是公共函数(public标志)

由Spring的AOP的特殊决定,入口函数必须是public,否则事务不起作用。当然这个问题实际开发中很少出现,因为定义的接口默认权限就是public。