简体   繁体   中英

spring @Transactional annotation

I have an abstract class and two sub classes that extend it. I have the following in spring config file

<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" />

In my abstract class I have the following methods

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

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

My java code

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

This does not work. executeInsertUpdateQuery() executes just one native sql query. If I put @Transactional on imortDataToDB() it works but then it makes my transaction huge since inside that method I loop through all the rows in a file and insert the records in db.

This is one of the major pitfalls in Spring - if you call @Transactional -method from non-transactional method in the same class , the @Transactional is ignored (unless you use AspectJ weaving). This is not Spring problem per se - the EJB has the same shortcomings.

Unfortunately with interface-based and class-based proxies all you can do is to split your class in two:

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
    }

}

The whole hustle is caused by the internal implementation of AOP proxies in Spring. With the code above new transaction will be started every time you call b.executeInsertUpdateQuery() from non-transactional BeanA .

I wrote about it on my blog Spring pitfalls: proxying , Spring AOP riddle and Spring AOP riddle demystified .

Not quite sure, what the question is, but @Transactional wraps the entire method in one transaction so obviously it will be huge if you import everything in one method. The advantage is, that if at some place your import fails, the entire transaction will not get executed and no faulty data is in your database.

If you don't want that, you'll have to manage the transactions yourself or call a @Transactional annotated method for a subset of your data, like you're doing right now for one import, but maybe you do it for 10 files or other eg logical restrictions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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