2013-06-27 39 views
32

@Transactional我想在我的應用程序的開始處讀取文本數據夾具(CSV文件)並將其放入我的數據庫中。@PostConstruct方法

爲此,我已經創建了一個PopulationService與一個初始化方法(@PostConstruct註釋)。

我也希望他們在一筆交易中執行,因此我在同一個方法中加入了@Transactional

但是,@Transactional似乎被忽略: 事務在我的低級DAO方法開始/停止。

我需要手動管理交易嗎?

回答

64

,這可能是有幫助的(http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct):

在@PostConstruct(與afterPropertiesSet方法從InitializingBean接口僅)是沒有辦法,以確保所有的後處理已經完成,所以(實際上)不可能有交易。確保工作的唯一方法是使用TransactionTemplate。

所以,如果你想在你的@PostConstruct你必須做這樣的事情的東西被事務中執行:

@Service("something") 
public class Something { 

    @Autowired 
    @Qualifier("transactionManager") 
    protected PlatformTransactionManager txManager; 

    @PostConstruct 
    private void init(){ 
     TransactionTemplate tmpl = new TransactionTemplate(txManager); 
     tmpl.execute(new TransactionCallbackWithoutResult() { 
      @Override 
      protected void doInTransactionWithoutResult(TransactionStatus status) { 
       //PUT YOUR CALL TO SERVICE HERE 
      } 
     }); 
    } 
} 
+0

無論如何,我們可以攔截容器的「完成後處理」事件,以便我們知道交易現在可用嗎? – gerrytan

+0

@gerrytan我相信這樣的事情可以通過使用Spring的[ApplicationListener](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationListener.html)來實現。它允許監聽包括上下文生命週期事件在內的各種事件。 –

+0

@gerrytan特別是[ContextRefreshedEvent](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/event/ContextRefreshedEvent.html)應該滿足您的需求。每[文檔](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#context-functionality-events):_「...所有的豆都加載,後處理器bean被檢測和激活,單例被預先實例化,並且ApplicationContext對象已準備好使用...「_ –

13

我認爲@PostConstruct只確保您的當前課程的預處理/注入完成。這並不意味着整個應用程序上下文的初始化已完成。

但是你可以使用Spring事件系統來接收事件時,應用程序上下文的初始化完成:

public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> { 
    public void onApplicationEvent(ContextRefreshedEvent event) { 
    // do startup code .. 
    }  
} 

查看文檔部分Standard and Custom Events更多的細節。

+0

不過,如何讓我的「初始化」方法的事務? –

+0

你有沒有試過從'onApplicationEvent()'方法調用你的transactional服務? – micha

+0

你是對的,使用@Transactional這是最好的解決方案 –

0

@Platon Serbin稱的回答並沒有爲我工作。所以我一直在尋找,發現了下面的答案,挽救了我的生命。 :d

答案就在這裏No Session Hibernate in @PostConstruct,我冒昧地抄寫:

@Service("myService") 
@Transactional(readOnly = true) 
public class MyServiceImpl implements MyService { 

@Autowired 
private MyDao myDao; 
private CacheList cacheList; 

@Autowired 
public void MyServiceImpl(PlatformTransactionManager transactionManager) { 

    this.cacheList = (CacheList) new TransactionTemplate(transactionManager).execute(new TransactionCallback(){ 

     @Override 
     public Object doInTransaction(TransactionStatus transactionStatus) { 

      CacheList cacheList = new CacheList(); 
      cacheList.reloadCache(MyServiceImpl.this.myDao.getAllFromServer()); 

      return cacheList; 
     } 

    }); 
} 
相關問題