bootstrap 数据加载中提示_解决Quartz定时器中查询懒加载数据no session的问题
作者:下一秒升華
出自:CSDN
原文:blog.csdn.net/u013815546/article/details/53032445
相信大家在web開發(fā)過程中一定遇到過一種情況,Class班級類一對多關聯(lián)一個Student學生類,所以為了性能考慮,配置一個lazy-init=true,然后在前臺頁面需要訪問懶加載數(shù)據(jù)時需要額外配置一個OpenSessionInViewFilter,但是可能并不知道這個過濾器到底做了什么,遇到Quartz定時中訪問懶加載問題配置這個filter可沒有用了,下面來討論下,怎么解決這個問題。
實驗之前先構(gòu)造兩個實體類,實現(xiàn)懶加載
@Entity @Table(name = "clazz") public class Clazz {@Id@GenericGenerator(name = "PKUUID", strategy = "uuid2")@GeneratedValue(generator = "PKUUID")@Column(length = 36)private String id;private String clazzName;private String clazzNumber;@OneToMany(fetch = FetchType.LAZY,mappedBy = "clazz",cascade = CascadeType.ALL)private List<Student> students;get/set... }Student類省略,我們現(xiàn)在數(shù)據(jù)手動插入一條記錄,待會我們在定時器里面查詢他。
定時任務代碼如下:
/*** Created by xujingfeng on 2016/11/3*/ public class DemoJob {@AutowiredClazzDao clazzDao;public static final Logger logger = LoggerFactory.getLogger(DemoJob.class);public DemoJob() {System.out.println("DemoJob=====>init");}public void run() {Clazz clazz = clazzDao.findOne("ba9071fb-f2da-481a-9a90-371022cda195");System.out.println(clazz.getClazzName());System.out.println(clazz.getClazzNumber());System.out.println(clazz.getStudents());logger.info("run============================@" + new Date());}}我們先不做額外配置看看運行結(jié)果
計算機 131 2016-11-04 10:16:50.213 ERROR 6692 --- [ryBean_Worker-1] org.quartz.core.JobRunShell : Job job_work.job_name threw an unhandled Exception: org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'run' on target class [class com.example.quartz.job.DemoJob] failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.quartz.common.entity.Clazz.students, could not initialize proxy - no Session可以看到,非懶加載數(shù)據(jù)可以順利查出來,但是懶加載數(shù)據(jù)會報no session
很明顯,session已經(jīng)關閉了。
- 解決方案1
關閉懶加載,好吧,當我沒講 - 解決方案2
給定時器調(diào)度的方案用事務包裹 
原理就是,用事務包裹之后,會當做一個整體,沒有提交時session不會交給SessionFactory管理
- 解決方案3
既然session關閉了,那就打開它就行了,類似于OpensessionInView,不過要取決于你的持久化方案來決定到底打開什么,一般是SessionFactory或者EntityManager,由于我是采用的JPA,所以使用后者 
配置一個任務監(jiān)聽器,用于打開session
public class OpenEntityManagerJobListener extends JobListenerSupport implements ApplicationContextAware {@Overridepublic String getName() {return "OpenEntityManagerJobListener";}EntityManagerFactory entityManagerFactory;@Overridepublic void jobToBeExecuted(JobExecutionContext context) {entityManagerFactory = applicationContext.getBean(EntityManagerFactory.class);EntityManager entityManager = entityManagerFactory.createEntityManager();EntityManagerHolder emHolder = new EntityManagerHolder(entityManager);TransactionSynchronizationManager.bindResource(entityManagerFactory, emHolder);}@Overridepublic void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(entityManagerFactory);EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());}ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;if(this.applicationContext ==null) throw new RuntimeException("applicationContext is null");} }之后記得給調(diào)度器注冊全局任務監(jiān)聽器,對所有任務監(jiān)聽
//調(diào)度工廠@Beanpublic SchedulerFactoryBean schedulerFactoryBean() {SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();factoryBean.setTriggers(triggerFactoryBeans().getObject());factoryBean.setGlobalJobListeners(openEntityManagerJobListener());return factoryBean;}再來試試運行一下定時任務
2016-11-04 10:29:12.234 INFO 11188 --- [ main] com.example.quartz.CommonApp : Started CommonApp in 12.067 seconds (JVM running for 12.675) 計算機 131 Hibernate: select students0_.clazz_id as clazz_id4_1_0_, students0_.id as id1_1_0_, students0_.id as id1_1_1_, students0_.clazz_id as clazz_id4_1_1_, students0_.stu_name as stu_name2_1_1_, students0_.stu_numer as stu_numer3_1_1_ from student students0_ where students0_.clazz_id=? [com.example.quartz.common.entity.Student@2cd010f8, com.example.quartz.common.entity.Student@100a20c4] 2016-11-04 10:29:12.336 INFO 11188 --- [ryBean_Worker-1] com.example.quartz.job.DemoJob : run============================@Date打完收工
總結(jié)
以上是生活随笔為你收集整理的bootstrap 数据加载中提示_解决Quartz定时器中查询懒加载数据no session的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 三星Galaxy S23 Ultra又出
 - 下一篇: 稳了!索尼PS4/PS5之父操刀新一代P