アプリケーションの開始時にテキストデータフィクスチャ(CSVファイル)を読み取り、データベースに配置したい。
そのために、初期化メソッドでPopulationServiceを作成しました(@ PostConstructアノテーション)。
また、それらを単一のトランザクションで実行したいので、同じメソッドに@ Transactionalを追加しました。
ただし、@ Transactionalは無視されるようです。トランザクションは、低レベルのDAOメソッドで開始/停止されます。
トランザクションを手動で管理する必要がありますか?
これは役に立つかもしれません( http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct ):
(InitializingBeanインターフェースのafterPropertiesSetのように)@PostConstructには、すべての後処理が既に行われていることを保証する方法がないため、(実際には)トランザクションは存在できません。それが機能していることを確認する唯一の方法は、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
}
});
}
}
おもう @PostConstruct
は、現在のクラスの前処理/インジェクションのみが終了することを保証します。アプリケーションコンテキスト全体の初期化が終了したことを意味するものではありません。
ただし、春のイベントシステムを使用して、アプリケーションコンテキストの初期化が終了したときにイベントを受信できます。
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
// do startup code ..
}
}
詳細については、ドキュメントのセクション 標準およびカスタムイベント を参照してください。
更新として、Spring 4.2から@EventListener
注釈により、よりクリーンな実装が可能になります。
@Service
public class InitService {
@Autowired
MyDAO myDAO;
@EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event) {
event.getApplicationContext().getBean(InitService.class).initialize();
}
@Transactional
public void initialize() {
// use the DAO
}
}
@ Platon Serbinの答えは私にはうまくいきませんでした。だから私は検索を続け、私の命を救った次の答えを見つけました。 :D
答えはここにあります @ PostConstructにSession Hibernateはありません 、私は自由に書き起こしました:
@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;
}
});
}
Selfを注入し、それを通して_@Transactional
_メソッドを呼び出します
_public class AccountService {
@Autowired
private AccountService self;
@Transactional
public void resetAllAccounts(){
//...
}
@PostConstruct
private void init(){
self.resetAllAccounts();
}
}
_
自己注入をサポートしない古いSpringバージョンの場合、BeanFactory
を注入し、self
をbeanFactory.getBean(AccountService.class)
として取得します
_@PostConstruct
_または_@NoTransaction
_メソッドでtransactionOperations.execute()
を使用すると両方が機能します
_@Service
public class ConfigurationService implements ApplicationContextAware {
private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class);
private ConfigDAO dao;
private TransactionOperations transactionOperations;
@Autowired
public void setTransactionOperations(TransactionOperations transactionOperations) {
this.transactionOperations = transactionOperations;
}
@Autowired
public void setConfigurationDAO(ConfigDAO dao) {
this.dao = dao;
}
@PostConstruct
public void postConstruct() {
try { transactionOperations.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(final TransactionStatus status) {
ResultSet<Config> configs = dao.queryAll();
}
});
}
catch (Exception ex)
{
LOG.trace(ex.getMessage(), ex);
}
}
@NoTransaction
public void saveConfiguration(final Configuration configuration, final boolean applicationSpecific) {
String name = configuration.getName();
Configuration original = transactionOperations.execute((TransactionCallback<Configuration>) status ->
getConfiguration(configuration.getName(), applicationSpecific, null));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
}
}
_