Конфликтующие весенние графики - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть две запланированные задачи, которые выполняются через разные промежутки времени.Первая задача должна запускаться каждые 5 секунд, а вторая задача - каждые 10 минут.

@EnableScheduling
public class ScheduledTask {

    @Autowired
    private taskService taskService;

    @Scheduled(every 5 second)
    public void scheduleTaskA() {
        taskService.taskA()
    }

    @Scheduled(every 10 minute)
    public void scheduleTaskB() {
        taskService.taskB()
    }
}

public class TaskServiceImpl implements TaskService {

    @PersistenceContext
    private EntityManager entityManager;

    void taskA(){
        StoredProcedureQuery query = entityManager.createStoredProcedureQuery("callStoreProcedure1"); 

        if(query.execute()) 
            query.getSingleResult();        

    }

    void taskB(){
        StoredProcedureQuery query = entityManager.createStoredProcedureQuery("callStoreProcedure2"); 

        if(query.execute())
            query.getSingleResult();                    
    }
}

Каждый раз, когда запускается вторая задача, выдается java.lang.IllegalStateException: Session/EntityManager is closed.Похоже, первой задачей является закрытие entityManager.Как можно избежать этого без изменения аннотации @PersistenceContext?

Полная трассировка стека

java.lang.IllegalStateException: Session/EntityManager is closed
    at org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:357) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.engine.spi.SharedSessionContractImplementor.checkOpen(SharedSessionContractImplementor.java:138) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.getMaxResults(AbstractProducedQuery.java:892) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.procedure.internal.ProcedureCallImpl.getResultList(ProcedureCallImpl.java:716) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.procedure.internal.ProcedureCallImpl.getSingleResult(ProcedureCallImpl.java:744) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
    at sun.reflect.GeneratedMethodAccessor150.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:374) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at com.sun.proxy.$Proxy149.getSingleResult(Unknown Source) ~[na:na]
    at com.test.service.TaskServiceImpl.taskA(TaskServiceImpl.java:602) ~[classes/:0.0.1-SNAPSHOT]
    at com.test.service.TaskServiceImpl....(TaskServiceImpl.java:112) ~[classes/:0.0.1-SNAPSHOT]
    at com.test.service.TaskServiceImpl....(TaskServiceImpl.java:163) ~[classes/:0.0.1-SNAPSHOT]
    at com.test.schedule.ScheduledTask.scheduledTaskA(ScheduledTask.java:45) ~[classes/:0.0.1-SNAPSHOT]
    at sun.reflect.GeneratedMethodAccessor143.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_171]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_171]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Вы получаете сообщение об ошибке, потому что пытаетесь использовать одного и того же менеджера сущностей.Это недолговечный объект.

Вы можете применить следующие два решения:

1) Inject EntityManagerFactory и внутри EntityManager, в методе используйте factory для создания EntityManager.

  @PersistenceUnit(unitName= "em")
  private EntityManagerFactory emf; 

2) Создайте два разных сервиса, чтобы у каждого сервиса был свой экземпляр администратора сущностей.(Не уверен, что он будет работать во второй раз, когда метод будет вызываться планировщиком. Протестируйте его и дайте мне знать.)

0 голосов
/ 08 января 2019

Я почти уверен, что вам нужно запускать StoredProcedureQuery (s) в транзакционном контексте.Попробуйте добавить @Transactional к каждому из ваших методов.

@Transactional
void taskA(){
    StoredProcedureQuery query = entityManager.createStoredProcedureQuery("callStoreProcedure1"); 

    if(query.execute()) 
        query.getSingleResult();        

}

@Transactional
void taskB(){
    StoredProcedureQuery query = entityManager.createStoredProcedureQuery("callStoreProcedure2"); 

    if(query.execute())
        query.getSingleResult();                    
}

Возможно, вы также захотите установить распространение на новое, чтобы каждый из них выполнялся в отдельной транзакции @Tansacational (распространение = Propagation.REQUIRES_NEW).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...