我想使用Quartz,Spring和Hibernate创建动态作业 . 用户与Web服务交互以创建此类的 jobs :
public class StartJobSpring extends QuartzJobBean {
private String jobId;
private String jobType;
@Autowired
private NoaJobInstancesDAO njiDAO;
@Transactional
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
JobKey key = context.getJobDetail().getKey();
JobDataMap dataMap = context.getMergedJobDataMap();
// some logic
njiDAO.create(instanceUUID, noaJob.getNoaJob(jobId), jobType);
}
}
NoaJobInstancesDAO 是一个简单的DAO类,它使用了Hibernate的 EntityManager :
@Repository
public class NoaJobInstancesDAOHibImpl implements NoaJobInstancesDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public NoaJobInstanceJPA create(NoaJobInstanceJPA entity) {
entityManager.persist(entity);
return entity;
}
@Override
public void create(String instance_uuid, NoaJobJPA job, String job_type) {
NoaJobInstanceJPA entity = new NoaJobInstanceJPA(instance_uuid, job,
job_type, "CREATED", null, null, "", "N", "N");
this.create(entity);
}
}
问题是当这个作业触发时,会抛出异常:
javax.persistence.TransactionRequiredException: No transactional EntityManager available
我无法理解为什么!我在 Manager 课程中以这种方式安排工作
JobDetail job = newJob(StartJobSpring.class).withIdentity(//anId)
.setJobData(//aJobMap).build();
getScheduler().getObject().scheduleJob(job, trigger);
调度程序连接到管理器的位置
@Autowired
private ApplicationContext applicationContext;
@Bean
SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JpaTransactionManager transactionManager) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
bean.setJobFactory(jobFactory);
bean.setTransactionManager(transactionManager);
return bean;
}
AutowiringSpringBeanJobFactory类与Autowiring相同 .
在我的观点中,调度程序布线有问题 . 实际上,我不明白如何检索应用程序上下文 .
EDIT1: 应用程序上下文似乎已正确实例化 . 问题不可能存在 .
EDIT2: 我正在使用单个配置bean(不是xml文件) . 这里主要方法:
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("package");
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.OracleDialect");
jpaProperties.put("hibernate.show_sql", "false");
jpaProperties.put("hibernate.hbm2ddl.auto", "update");
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
@Bean
public NoaJobInstancesDAO noaJobInstancesDAO() {
NoaJobInstancesDAOHibImpl noaJobInstancesDAO = new NoaJobInstancesDAOHibImpl();
return noaJobInstancesDAO;
}
3 回答
您处于Spring托管上下文中,并尝试使用@PersistentContext访问EntityManager,这是一个javax.persistence注释 . 尝试使用@Autowire自动装配EntityManagerFactory bean,我假设您在spring-context.xml中配置它,并使用entityManagerFactory.createEntityManager()为您提供Spring管理实体管理器,该管理器将由spring包装并位于您定义的事务管理器中
SHORT SOLUTION: 让 Spring 天通过工厂做你的工作 .
LONG SOLUTION: 这里有详细描述 . 我通过导入xml配置文件修改了我的配置文件:
这样,您就有了一个生成作业实例的 spring 工厂 . 现在,这是我更新的java配置类
我用一个bean来安排工作 . 所以首先我在这个bean中注入工厂 . 然后当我想安排一个Job时,我会使用这个片段
我也修改了工作类
Problem solved!
我这样解决了这个问题:
在Job中(必须获得一个接口):
}
在应用程序的.xml上下文中:还需要在此xml中声明为bean: