transaction transacciones transaccional framework example driven con annotation spring transactions

spring - transacciones - @Transactional en el método @PostConstruct



transacciones con spring framework (5)

Creo que @PostConstruct solo garantiza que el preprocesamiento / inyección de tu clase actual haya finalizado. No significa que la inicialización de todo el contexto de la aplicación haya finalizado.

Sin embargo, puede usar el sistema de eventos de primavera para recibir un evento cuando finaliza la inicialización del contexto de la aplicación:

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

Consulte la sección de documentación Eventos estándar y personalizados para obtener más detalles.

Quiero leer los accesorios de datos de texto (archivos CSV) al inicio de mi aplicación y ponerlos en mi base de datos.

Para eso, he creado un PopulationService con un método de inicialización ( @PostConstruct anotación).

También quiero que se ejecuten en una sola transacción, y por lo tanto, agregué @Transactional en el mismo método.

Sin embargo, el @Transactional parece ser ignorado: la transacción se inicia / detiene en mis métodos DAO de bajo nivel.

¿Debo administrar la transacción manualmente?


El uso de transactionOperations.execute() en @PostConstruct o en el método @NoTransaction funciona

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


Inyectarse y llamar a través del @Transactional método @Transactional

public class AccountService { @Autowired private AccountService self; @Transactional public void resetAllAccounts(){ //... } @PostConstruct private void init(){ self.resetAllAccounts(); } }

Para versiones anteriores de Spring que no admiten la autoinyección, inyecte BeanFactory y obtenga self como beanFactory.getBean(AccountService.class)


La respuesta de @Platon Serbin no funcionó para mí. Así que seguí buscando y encontré la siguiente respuesta que me salvó la vida. :RE

La respuesta es aquí No Session Hibernate en @PostConstruct , que me tomé la libertad de transcribir:

@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; } }); }


esto podría ser útil ( http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct ):

En @PostConstruct (como con afterPropertiesSet desde la interfaz InitializingBean) no hay forma de garantizar que todo el procesamiento posterior ya esté hecho, por lo que (de hecho) no puede haber Transacciones. La única manera de asegurarse de que eso funcione es mediante el uso de una TransactionTemplate.

Entonces, si desea que se @PostConstruct algo en su @PostConstruct dentro de la transacción, debe hacer algo como esto:

@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 } }); } }