2012-01-26 3 views
5

У меня есть абстрактный класс и два подкласс, которые его расширяют. У меня есть следующие в весеннем конфигурационном файлеspring @Transactional annotation

<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 
} 

Мой ява код

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

Это не работает. executeInsertUpdateQuery() выполняет только один собственный SQL-запрос. Если я положил @Transactional на imortDataToDB(), он работает, но затем он делает мою транзакцию огромной, поскольку внутри этого метода я просматриваю все строки в файле и вставляю записи в db.

ответ

8

Это одна из главных ошибок, весной - если вы звоните @Transactional -метод из нетранзакционного метода в том же классе, то @Transactional игнорируется (если не использовать AspectJ ткачество). Это не проблема весны per se - 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. С кодом выше новая транзакция будет запускаться каждый раз, когда вы вызываете b.executeInsertUpdateQuery() из небанковских BeanA.

Я писал об этом в своем блоге Spring pitfalls: proxying, Spring AOP riddle и Spring AOP riddle demystified.

+0

Спасибо за быстрый ответ. – user373201

0

Не совсем уверен, что вопрос, но @Transactional обертывает весь метод за одну транзакцию, поэтому, очевидно, он будет огромным, если вы импортируете все в один метод. Преимущество состоит в том, что если в каком-то месте ваш импорт завершится неудачно, вся транзакция не будет выполнена, и в вашей базе данных не будет ошибок.

Если вы этого не хотите, вам придется самостоятельно управлять транзакциями или вызвать аннотированный метод @Transactional для подмножества ваших данных, например, сейчас вы используете один импорт, но, возможно, вы это делаете для 10 файлов или других, например логические ограничения.

Смежные вопросы