복붙노트

[SPRING] @PostConstruct 메서드의 @Transactional

SPRING

@PostConstruct 메서드의 @Transactional

내 응용 프로그램의 시작 부분에 텍스트 데이터 비품 (CSV 파일)을 읽고 데이터베이스에 저장하려고합니다.

이를 위해 초기화 메소드 (@PostConstruct annotation)로 PopulationService를 만들었습니다.

또한 이들을 단일 트랜잭션으로 실행해야하므로 동일한 메소드에서 @Transactional을 추가했습니다.

그러나 @Transactional은 무시되는 것처럼 보입니다. 트랜잭션은 낮은 수준의 DAO 메소드에서 시작 / 중지됩니다.

수동으로 트랜잭션을 관리해야합니까?

해결법

  1. ==============================

    1.이 도움이 될 수 있습니다 (http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct).

    이 도움이 될 수 있습니다 (http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct).

    따라서 @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
                }
            });
       }
    }
    
  2. ==============================

    2.@PostConstruct는 현재 클래스의 전처리 / 삽입이 완료되었음을 보장합니다. 전체 응용 프로그램 컨텍스트의 초기화가 완료되었음을 의미하지는 않습니다.

    @PostConstruct는 현재 클래스의 전처리 / 삽입이 완료되었음을 보장합니다. 전체 응용 프로그램 컨텍스트의 초기화가 완료되었음을 의미하지는 않습니다.

    그러나 스프링 이벤트 시스템을 사용하여 응용 프로그램 컨텍스트의 초기화가 완료되면 이벤트를 수신 할 수 있습니다.

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

    자세한 내용은 표준 및 사용자 정의 이벤트 설명서를 참조하십시오.

  3. ==============================

    3.@ Platon Serbin의 대답이 저에게 효과적이지 않았습니다. 그래서 계속해서 내 삶을 살리는 다음과 같은 대답을 찾았습니다. :디

    @ Platon Serbin의 대답이 저에게 효과적이지 않았습니다. 그래서 계속해서 내 삶을 살리는 다음과 같은 대답을 찾았습니다. :디

    그 대답은 @PostConstruct의 No 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;
            }
    
        });
    }
    
  4. ==============================

    4.@PostConstruct 나 @NoTransaction 메소드에서 transactionOperations.execute ()를 사용하면

    @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 {
    
        }
    }
    
  5. ==============================

    5.자기를 주입하고 그것을 통해 @Transactional 메서드 호출

    자기를 주입하고 그것을 통해 @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)

  6. from https://stackoverflow.com/questions/17346679/transactional-on-postconstruct-method by cc-by-sa and MIT license