2015-08-11 5 views
0

У меня есть специальный поток в моем приложении Spring.Spring TransactionTemplate, вызванный методом @Transaction

У меня есть репозиторий, и я вызываю метод sell() как первый звонок.

@Service 
@Transactional 
public class ServiceRepositoryImpl implements ServiceRepository { 

@Inject 
private SellRepository sellRepository; 

@Override 
public long sell(long id) 
    .... 
    .... 
    .... 
    Sell sell = new Sell(); 
    ... 
    sellRepository.save(sell); 
} 

и мой SellService:

@Service 
public class SellRepositoryImpl implements SellRepository { 

@PersistenceContext 
private EntityManager entityManager; 

@Inject 
SellHelperRepository sellHelperRepository; 

@Inject 
private TransactionTemplate transactionTemplate; 

@Override 
public <S extends Sell> S save(S sell) throws Exception {  

    transactionTemplate.execute(new TransactionCallback<S>() { 
     @Override 
     public S doInTransaction(TransactionStatus status) { 
      try { 
       ... 
       entityManager.persist(sell); 
      } catch (Throwable e) { 
       log.error("", e); 
       status.setRollbackOnly(); 
      } 
      return vendita; 
     } 
    });  

    sellHelperRepository.createTickets(sell.getId()); 


    return vendita; 
} 

это мой sellHelperRepository:

@Service 
@Transactional 
public class SellHelperRepositoryImpl implements SellHelperRepository { 

@PersistenceContext 
private EntityManager entityManager; 

@Override 
@Async 
public void createTickets(long sellID) { 
    Sell sell = entityManager.find(Sell.class, sellID); 
    try{ 
     ... 
     Ticket t = new Ticket(); 
     ticketService.save(t); 
    }catch(Throwable e){ 
     sell.setStatus("CANCELED"); 
    } 
} 

и в конце концов мой Услуги по продаже билетов:

@Service 
@Transactional 
public class TicketRepositoryImpl implements TicketRepository { 

@PersistenceContext 
protected EntityManager entityManager; 

@Override 
@Transactional(propagation = Propagation.REQUIRES_NEW) 
public Biglietto save(Ticket ticket) throws Exception { 
     entityManager.persist(ticket); 
} 

Проблема заключается в том, что в этом цепочка звонков, когда я нахожусь SellRepositoryImpl, объект продается не сохраняется как можно скорее, я вышел из транзакции, но это должно быть! Поэтому, когда я вхожу в SellHelperRepositoryImpl, и я пытаюсь найти его, он его не найдет!

Эта конкретная структура необходима, поскольку эти методы используются также из другого хранилища. Я создал много тестов junit, чтобы проверить, все ли работает нормально; для остальных тестов все работает нормально, часть для этой конкретной цепи вызовов.

Я думаю, что я что-то не хватает ....

Благодаря

ответ

1

проблема с вашим кодом является то, что вы используете @Async на createTickets метод, который заставляет пружину, чтобы выполнить его в разные нить со «свежей» транзакцией, поэтому вам нужно выполнить флеш/фиксацию первой транзакции, которая была открыта в классе SellRepositoryImpl. Таким образом, вы можете пойти тремя путями

  • Удалите @Async из createTickets метода
  • Смените уровня изоляции транзакций от DEFAULT к READ_UNCOMMITTED в SellHelperRepositoryImpl

    @Service 
    @Transactional(isolation=Isolation.READ_UNCOMMITTED) 
    public class SellHelperRepositoryImpl implements SellHelperRepository   { 
    
        @PersistenceContext 
        private EntityManager entityManager; 
    
        @Override 
        @Async 
        public void createTickets(long sellID) { 
         Sell sell = entityManager.find(Sell.class, sellID); 
         try{ 
          ... 
          Ticket t = new Ticket(); 
          ticketService.save(t); 
         }catch(Throwable e){ 
          sell.setStatus("CANCELED"); 
         } 
        } 
    
  • Промойте вручную управляемую транзакцию в save(S sell), см. Следующий фрагмент кода.

    @Override 
    public <S extends Sell> S save(S sell) throws Exception {  
    
        transactionTemplate.execute(new TransactionCallback<S>() { 
         @Override 
         public S doInTransaction(TransactionStatus status) { 
          try { 
           ... 
           entityManager.persist(sell); 
           entityManager.getTransaction().commit(); 
           status.flush(); 
          } catch (Throwable e) { 
           log.error("", e); 
           status.setRollbackOnly(); 
          } 
          return vendita; 
         } 
        });  
    
        sellHelperRepository.createTickets(sell.getId()); 
        return vendita; 
    } 
    
+0

Я попытался 3-е решение, но оно не работает. Транзакция не совершается в конце транзакции транзакцииTemplate.execute(). – drenda

+0

Извините, у меня нет IDE на этом компьютере, поэтому попробуйте выполнить транзакцию вручную с помощью entityManager.getTransaction(). Commit(); Я скорректировал код. – Babl

+0

Я не могу использовать entityManager.getTransaction(). Commit(); потому что в противном случае мне не разрешено создавать транзакцию в shared EntityManager - вместо этого используйте Spring-транзакции или EJB CMT. На данный момент рабочим решением является установка PROPAGATION_REQUIRES_NEW в transactionTemplate. – drenda

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