1、org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean报 java.io.NotSerializableException异常,须要本身实现QuartzJobBean。
2、dao必需要实现序列化接口,Hibernate dao不能直接继承自HibernateDaoSupport,由于HibernateDaoSupport没有实现序列化接口,只能经过SessionFactory构造HibernateTemplate。
3、当库里己存在Trigger,应用启动时会从库里加载己存在Trigger,会报java.io.InvalidObjectException: Could not find a SessionFactory named: null等SessionFactory等相关异常。由于应用每次启动的获得的SessionFactory实例是不同的,当从库里取到的Job进行反序列化时,Job里包含的SessionFactory与当前的SessionFactory不一致,因此为nulljava
4、一旦QuartzJobBean类或里面的属性被修改,那么数据库中对应的qrtz_job_details保存的job_class_name仍是之前的QuartzJobBean,这致使这个旧的job再一次从新执行时,会找不到相应的QuartzJobBean,而报空指针异常。web
第二个问题与第三个是互相关联的,我想到要解决这两个问题的一个方案是Job中不要包含SessionFactory就没一切OK了, 由于SessionFactory是hibernate dao的属性,而hibernate dao是SimpleService的属性,所以SimpleService不能有任何hibernate dao属性了。如此SimpleService业务方法里须要的hibernate dao又如何获取呢?对 spring 的了解,咱们知道能够经过ApplicationContext获取到任何spring bean,可是在这里ApplicationContext又怎么获取呢? ... 查看org.springframework.web.context.ContextLoaderListener找到org.springframework.web.context.ContextLoader.getCurrentWebApplicationContext()能够获取到ApplicationContext,增长一个SpringBeanService类,实现序列化接口,经过SpringBeanService能够获取到web己经加载的spring beanspring
package com.sundoctor.example.service;
import java.io.Serializable;
import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.springframework.web.context.ContextLoader;
@SuppressWarnings("unchecked") @Service("springBeanService") public class SpringBeanService implements Serializable{
private static final long serialVersionUID = -2228376078979553838L;
public <T> T getBean(Class<T> clazz,String beanName){ ApplicationContext context = ContextLoader.getCurrentWebApplicationContext(); return (T)context.getBean(beanName); } }
由于Hibernate Dao再也不持久到Job中,所在再也不须要实现序列化接口,能够继承HibernateDaoSupport,固然也能够不继承,能够根据本身喜爱的方式编写,再也不有任何限制数据库
package com.sundoctor.example.dao;
import org.hibernate.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.stereotype.Repository;
import com.sundoctor.example.model.Customer; import com.sundoctor.example.service.CustomerService;
@Repository("customerDao") public class CustomerHibernateDao extends HibernateDaoSupport {
private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
public Customer getCustomer2() { return (Customer) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) { Customer customer = (Customer) session.createQuery("from Customer where id = 1").uniqueResult(); logger.info("Customer2={}", customer); return customer; } }); }
public Customer getCustomer1() { Customer customer = (Customer) this.getHibernateTemplate().get(Customer.class, 1); logger.info("Customer1={}", customer); return customer; }
}
由于hibernate dao 再也不实现序列化接口和继承自HibernateDaoSupport,不能再注入到业务类中了。在业务类中注入以上的SpringBeanService,业务方法须要的hibernate dao经过以上的SpringBeanService.getBean获取服务器
package com.sundoctor.example.service;
import java.io.Serializable;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service;
import com.sundoctor.example.dao.CustomerHibernateDao; import com.sundoctor.example.model.Customer;
@Service("customerService") public class CustomerService implements Serializable {
private static final long serialVersionUID = -6857596724821490041L; private static final Logger logger = LoggerFactory.getLogger(CustomerService.class); private SpringBeanService springBeanService;
@Autowired public void setSpringBeanService(@Qualifier("springBeanService") SpringBeanService springBeanService) { this.springBeanService = springBeanService; }
public void testMethod1() { // 这里执行定时调度业务 CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao"); Customer customer = customerDao.getCustomer1(); logger.info("AAAA:{}", customer);
}
public void testMethod2() { // 这里执行定时调度业务 CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao"); Customer customer = customerDao.getCustomer2(); logger.info("BBBB:{}", customer); }
customerService是咱们的Job具体执行的类,它必须实现序列化,由于它会被序列化到表qrtz_job_details中的job_class_name字段中,因此springBeanService属性也必须序列化,这里其实也能够不用写springbeanservice,而是直接在testMethod中使用applicationContext.getBean去拿到dao,而后进行业务操做。session
若是当任务执行的时间点上,正好服务器down掉或因为其余缘由任务没有顺利完成
该如何自动或手动唤醒它,让他顺利执行呢?app
//获取到Scheduler Scheduler scheduler = ...;//(Scheduler)springContext.getBean("quartzScheduler"); //经过trigger name和trigger group获得SimpleTrigger SimpleTrigger trigger = (SimpleTrigger)scheduler.getTrigger("52f071d3-eebb-4308-abeb-9ce8ec58aba4", "DEFAULT"); //从新设置Trigger己经触发的次数 int timesTriggered = trigger.getTimesTriggered(); trigger.setTimesTriggered(timesTriggered > 0 ? timesTriggered -1 : 0);
//可选,从新设置开始触发时间 //trigger.setStartTime(startTime); //可选,从新设置下次触发时间 //trigger.setNextFireTime(nextFireTime); //等等,还有许多可选配置能够从新设置
//调用rescheduleJob从新调度tirgger scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);