1. 程式人生 > >解決Quartz定時器中查詢懶載入資料no session的問題

解決Quartz定時器中查詢懶載入資料no session的問題

相信大家在web開發過程中一定遇到過一種情況,Class班級類一對多關聯一個Student學生類,所以為了效能考慮,配置一個lazy-init=true,然後在前臺頁面需要訪問懶載入資料時需要額外配置一個OpenSessionInViewFilter,但是可能並不知道這個過濾器到底做了什麼,遇到Quartz定時中訪問懶載入問題配置這個filter可沒有用了,下面來討論下,怎麼解決這個問題。

實驗之前先構造兩個實體類,實現懶載入

@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類省略,我們現在資料手動插入一條記錄,待會我們在定時器裡面查詢他。

定時任務程式碼如下:

/**
 * Created by xujingfeng on 2016/11/3
 */
public class DemoJob {

    @Autowired
    ClazzDao 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("[email protected]" + new Date()); } }

我們先不做額外配置看看執行結果

計算機
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

可以看到,非懶載入資料可以順利查出來,但是懶載入資料會報no session

很明顯,session已經關閉了。

  • 解決方案1
    關閉懶載入,好吧,當我沒講
  • 解決方案2
    給定時器排程的方案用事務包裹
@Transactional
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("[email protected]" + new Date());

    }

原理就是,用事務包裹之後,會當做一個整體,沒有提交時session不會交給SessionFactory管理

  • 解決方案3
    既然session關閉了,那就開啟它就行了,類似於OpensessionInView,不過要取決於你的持久化方案來決定到底開啟什麼,一般是SessionFactory或者EntityManager,由於我是採用的JPA,所以使用後者

配置一個任務監聽器,用於開啟session

public class OpenEntityManagerJobListener extends JobListenerSupport implements ApplicationContextAware {

    @Override
    public String getName() {
        return "OpenEntityManagerJobListener";
    }

    EntityManagerFactory entityManagerFactory;

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        entityManagerFactory = applicationContext.getBean(EntityManagerFactory.class);
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityManagerHolder emHolder = new EntityManagerHolder(entityManager);
        TransactionSynchronizationManager.bindResource(entityManagerFactory, emHolder);
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(entityManagerFactory);
        EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
    }


    ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        if(this.applicationContext ==null) throw new RuntimeException("applicationContext is null");
    }
}

之後記得給排程器註冊全域性任務監聽器,對所有任務監聽

//排程工廠
    @Bean
    public 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           : [email protected]

打完收工

相關推薦

解決Quartz定時查詢載入資料no session的問題

相信大家在web開發過程中一定遇到過一種情況,Class班級類一對多關聯一個Student學生類,所以為了效能考慮,配置一個lazy-init=true,然後在前臺頁面需要訪問懶載入資料時需要額外配置一個OpenSessionInViewFilter,但是可能並

Quartz定時Service注入時空指標問題解決

上週在做一個任務排程時,用到了Quartz定時器,用的xml配置方式,隨後進行資料庫操作時,發現service注入不進去,報空指標錯誤,然後網上查了一些資料,找到了一個比較好的解決方法,詳情如下: 1.      問題:用qu

Quartz定時Cron時間控制表示式寫法

Quartz定時器中Cron時間控制表示式寫法:   1、表示形式 該表示式簡潔簡單,總共有7個空格分割的表達子式,形式為【* * * * * * *】,而這七個位置上的東西表達方式有很多,意義從左往右依次是:秒 分 時 日 月 周 年,往往,“年”這個標誌位可以不寫,而

解決hibernate載入問題No session的問題

<!-- 解決懶載入問題 --> <filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframewo

spring quartz定時配置-JobStoreTX方式持久化在資料庫

配置quartz持久化在資料庫中,同樣需要以下三步配置,如下: 首先需要引入quartz所依賴的jar包 建立quartz_jobs.xml檔案用於配置排程器 引入quartz_jobs.xml 只是在為quartz定時器配置資料庫時,在quartz_jobs.xm

SSM Quartz(定時)的使用

本人使用: 整合開發環境:idea 專案管理工具:maven 資料庫:oracle 框架:Spring+SpringMVC+myBatis 主要步驟: 在pom.xml中加入外掛依賴 編寫需要定時執行的方法類 編寫spring-quartz.xml配置檔案

spring整合quartz定時的專案,如何關閉不斷輸出的batch acquisition of 0 triggers ?

不斷輸出的batch acquisition of 0 triggers太鬧心了,嚴重影響了除錯效率,不能忍,經過查閱資料得出關閉方法。希望幫助更多的小夥伴。解決方法:在pom.xml中看看使用的是哪個

Spring的quartz定時同一時刻重複執行二次的問題解決

最近用Spring的quartz定時器的時候,發現到時間後,任務總是重複執行兩次,在tomcat或jboss下都如此。 打印出他們的hashcode,發現是不一樣的,也就是說,在web容器啟動的時候,重複啟了兩個quartz執行緒。 研究下來發現quartz確實會載入兩次: 第一次:web容器啟動的時候,

使用python顯示影象在windows圖片檢視一直顯示載入就是打不開的解決途徑

在win7下面使用PIL中Image的show()函式時,執行下列程式碼: 發現圖片在windows圖片檢視器中一直顯示載入中就是打不開 解決方法:(X為python的安裝碟符) X:\Python\lib\site-packages\PIL\ImageS

stm8l定時的ARPE

bit enabled 不同 err ear pre 寫入 作用 sha • Auto-reload preload enabled (ARPE bit set in the TIM1_CR1 register). In this mode,when data i

spring整合Quartz定時

() void java類 info throws tex execute new protect 第一種:為普通java類中的某個方法配置跑批任務 1.定義要跑批的類和方法: package com.xy.utils.quartz; import org.joda.t

quartz定時實現

quartz總結:要實現定時器quartz,我們註意兩步就行了,一是寫好實現類註意實現類的方法名要和配置中一致,二是做好配置。然後就可以測試了。①定時器實現類HealthRecodersTokenScheduler.javapublic class HealthRecodersTokenScheduler {

string整合Quartz定時

調度 obd ont 觸發 lfa sta 每天 cron表達式 PE 直接上配置文件,此方法只需要配置好配置文件就行 1 <!--配置調度器--> 2 <bean name="startQuertz" lazy-init="false" a

springboot整合quartz定時實現定時任務詳解

最近需要 做一個按照時間,定時初始化一些資訊的功能,研究了一下quartz,也簡單瞭解一下TimerTask,廢話不多說。 quartz和TimerTask的區別: timer是jdk自帶的(可想而知,肯定是不怎麼好用)。 Quartz可以通過cron表示式精確到特定時間執行,而T

Quartz 定時的時間設定

    時間的配置如下:<value>0 26 16 * * ?</value>    時間大小由小到大排列,從秒開始,順序為 秒,分,時,天,月,年    *為任意 ?為無限制。 由此上面所配置的內

CAD編輯查詢文字的功能選項在哪裡?

CAD編輯器中查詢文字的功能選項在哪裡?在編輯CAD圖紙的過程中是藉助CAD編輯器來進行繪製的,而且在圖紙中會有許多的地方需要進行標註,如果我們需要在一次查詢該文字的時候,如何使用CAD編輯器中的查詢文字功能,那CAD中查詢CAD圖紙中文字的功能選項在哪裡了?下面我們就一起來看看吧!有興趣的朋友也可以一起來看

spring-quartz 定時 給targetMethod傳遞引數

今天在做一個專案的時候,要給一個定時器任務的執行方法傳遞引數,在網上找了一下資料,可以使用arguments引數:   <bean id="subsidyJobDetail" class="org.springframework.scheduling.quartz

java定時、Spring定時Quartz定時

   當前java程式中能夠實現定時的主要有三種方式,分別是:java定時器,spring定時器,quartz定時器。    下面依次講講他們的應用! java定時器的應用    其實java很早就有解決定時器任務的方法了,ja

springboot使用Quartz定時

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> <

quartz定時 Job的execute使用動態引數

@GetMapping({"/addSearchIndexBySite"}) public JsonResult addSearchIndexBySite(@RequestParam(required = false) String site) throws SchedulerE