我有一个抽象类和两个扩展它的子类。我在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中插入记录。
答案 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: proxying,Spring AOP riddle和Spring AOP riddle demystified上写过这篇文章。
答案 1 :(得分:0)
不太确定,问题是什么,但@Transactional
将整个方法包装在一个事务中,所以如果在一个方法中导入所有内容,显然会很大。优点是,如果在某个地方导入失败,整个事务将无法执行,数据库中也没有错误的数据。
如果你不想那样,你必须自己管理这些交易,或者为你的数据子集调用@Transactional
带注释的方法,就像你现在正在进行一次导入一样,但也许你为10个文件或其他文件做到这一点逻辑限制。