spring @Transactional注释

时间:2012-01-26 15:03:58

标签: java spring

我有一个抽象类和两个扩展它的子类。我在spring配置文件中有以下内容

<bean id="importConfigFile" class="xxx.ImportConfigFiles" parent="parentImportFile"></bean>

<bean id="importFile" class="xxx.ImportUMTSKPIFiles" parent="parentImportFile"></bean>

<bean id="parentImportFile" name="parentImportFile" class="xxx.ImportUMTSFiles" abstract="true"></bean>

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

在我的抽象课中,我有以下方法

public void importDataToDB(){
    //all the good stuff goes in here
}

@Transactional
public void executeInsertUpdateQuery(){
    //all the good stuff goes in here
}

我的java代码

ImportConfigFiles importConfigFiles = (ImportConfigFiles)context.getBean("importConfigFile");
importConfigFiles.setFileLocation(destPath);
importConfigFiles.importDataToDB();

这不起作用。 executeInsertUpdateQuery()只执行一个本机sql查询。如果我将@Transactional放在imortDataToDB()上它可以工作但是它会使我的事务变得很大,因为在该方法中我循环遍历文件中的所有行并在db中插入记录。

2 个答案:

答案 0 :(得分:8)

这是Spring中的主要陷阱之一 - 如果您在同一类中使用非事务性方法调用@Transactional - 方法,则忽略@Transactional(除非你使用AspectJ编织)。这不是Spring问题本身 - EJB具有相同的缺点。

不幸的是,对于基于接口和基于类的代理,您所能做的就是将您的课程分成两部分:

public class BeanA() {

    @Resource
    private BeanB b;

    public void importDataToDB(){
        b.executeInsertUpdateQuery();
    }
}

public class BeanB {

    @Transactional
    public void executeInsertUpdateQuery(){
        //all the good stuff goes in here
    }

}

整个喧嚣是由Spring中AOP代理的内部实现引起的。使用上面的代码,每次从非交易b.executeInsertUpdateQuery()拨打BeanA时,都会启动新的交易。

我在我的博客Spring pitfalls: proxyingSpring AOP riddleSpring AOP riddle demystified上写过这篇文章。

答案 1 :(得分:0)

不太确定,问题是什么,但@Transactional将整个方法包装在一个事务中,所以如果在一个方法中导入所有内容,显然会很大。优点是,如果在某个地方导入失败,整个事务将无法执行,数据库中也没有错误的数据。

如果你不想那样,你必须自己管理这些交易,或者为你的数据子集调用@Transactional带注释的方法,就像你现在正在进行一次导入一样,但也许你为10个文件或其他文件做到这一点逻辑限制。