0

在 @PostConstruct 中持久化对象时,我的 Entitymanager 没有事务。我不知道为什么以及如何解决这个问题,有人可以帮助我吗?

PS。如果您需要任何其他数据,请询问

测试机管理器

@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)
4

1 回答 1

0

您在 @PostConstruct 中有一个用于 Singleton bean 的事务。您丢失交易的那一刻是您使用timer.schedule(checker, safetycheckAt());or启动新计时器的时候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
    }
}

我没有测试代码,它只是粗略的代码。希望能帮助到你。

于 2012-12-18T14:59:11.153 回答