在@PostConstruct中持久保存对象时,My Entitymanager没有事务。 我不知道为什么以及如何解决这个问题,任何人都可以帮助我吗?
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 :(得分:0)
在@PostConstruct中有一个针对Singleton bean的事务。当您丢失交易时,就是当您使用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
}
}
我没有测试代码,只是粗略的代码。希望它有所帮助。