2012-12-18 88 views
0

在@PostConstruct中持久化對象時,我的Entitymanager沒有事務。 我不知道爲什麼以及如何解決這個問題,任何人都可以幫助我嗎?堅持@PostConstruct:javax.persistence.TransactionRequiredException

PS。如果您需要任何其他數據,請向

TestmachineManager

@Singleton 
public class TestmachineManager { 
    @PersistenceContext 
    private EntityManager em; 

    private TimerTask handler = new TimerTask() { 
     @Override 
     public void run() { 
      DayPlanning planning = getPlanning(); 
      Order order = planning.getNextInLine(); 
      if(order instanceof Order) { 
       em.merge(planning); 
       List<String> tests = new ArrayList(); 
       for(Test test : order.getTests()) { 
        tests.add(test.getName()); 
       } 

       TestmachineSender.orderTests(order.getId(), order.getDomain(), tests); 
       timer.schedule(checker, safetycheckAt()); 
      } 
      else { 
       timer.schedule(handler, postponeTo()); 
      } 
     } 
    }; 

    @PostConstruct 
    public void init() { 
     if(getPlanning().hasActiveTest()) { 
      handler.run(); 
     } 
    } 

    private DayPlanning getPlanning() { 
     LocalDate today = new LocalDate(
       Calendar.getInstance().getTime()); 

     try { 
      CriteriaBuilder cb = em.getCriteriaBuilder(); 
      CriteriaQuery<DayPlanning> query = cb.createQuery(DayPlanning.class); 
      Root dayPlanning = query.from(DayPlanning.class); 
      Predicate predicateDate = cb.equal(dayPlanning.get("dateOfPlanning"), today.toDate()); 

      query.select(dayPlanning).where(predicateDate); 
      return em.createQuery(query).getSingleResult(); 
     } catch(NoResultException ex) { 
      DayPlanning newPlanning = new DayPlanning(today); 
      em.persist(newPlanning); 
      return newPlanning; 
     } 
    } 
} 

堆棧跟蹤

Caused by: javax.persistence.TransactionRequiredException 
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163) 
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145) 
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:263) 
    at TestmachineManager.getPlanning(TestmachineManager.java:130) 
    at TestmachineManager.init(TestmachineManager.java:78) 
+0

您是否嘗試過在getPlanning方法中重新打開一個新事務?我猜想加載對象的那個被關閉,實體分離。 –

+0

根據您的IOC容器,事務可能無法在@PostConstruct方法中工作。 http://www.java.net/node/669926這可能是你春季的解決方案。 http://www.tikalk.com/java/doing-transactional-work-spring-service-using-postconstruct-method – Parvez

回答

0

您有辛格爾頓豆在@PostConstruct交易。您丟失交易的那一刻是當您使用timer.schedule(checker, safetycheckAt());timer.schedule(handler, postponeTo());啓動新計時器時。我認爲你使用的計時器對象實際上是java.util.Timer,看着簽名。

您應該嘗試使用EJB TimerService資源。例如:

@Resource 
private TimerService timerService; 

@Timeout 
public void run() { 
    DayPlanning planning = getPlanning(); 
    Order order = planning.getNextInLine(); 
    if(order instanceof Order) { 
     em.merge(planning); 
     List<String> tests = new ArrayList(); 
     for(Test test : order.getTests()) { 
      tests.add(test.getName()); 
     } 

     TestmachineSender.orderTests(order.getId(), order.getDomain(), tests); 

     // if the checker handler doesn't need to run transactionally you could leave it like it was before 
     timer.schedule(checker, safetycheckAt()); 
     // otherwise you could create a checker EJB that uses @Timeout in the same manner or @Scheduled from EJB3.1 
    } else { 
     // postpone timer 
     timerService.createTimer(postponeTo(), "postponed timer information");  
    } 
} 

@PostConstruct 
public void init() { 
    if(getPlanning().hasActiveTest()) { 
     timerService.createTimer(computeDelay(), "timer information"); 
     // or you could use the other create methods of the timerService, those that fits your needs better 
    } 
} 

我沒有測試代碼,它只是粗略的代碼。希望能幫助到你。

+0

嗯,這聽起來很合理。我會試一試。感謝弗洛林的建議! – Aquillo