弹簧石英的问题

时间:2009-10-23 13:57:18

标签: java spring quartz-scheduler

我正在尝试基于一些间隔时间调用方法,这里是applicationContext.xml中的一些bean

<bean id="MngtTarget"
  class="com.management.engine.Implementation" 
  abstract="false" lazy-init="true" autowire="default" dependency-check="default">

    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
      <property name="targetObject" ref="MngtTarget" />
      <property name="targetMethod" value="findItemByPIdEndDate"/>
    </bean>


    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">

        <property name="jobDetail" ref="jobDetail" />
        <!-- 10 seconds -->
        <property name="startDelay" value="10000" />
        <!-- repeat every 50 seconds -->
        <property name="repeatInterval" value="20000" />
    </bean>


    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>

这是我试图调用的方法:

public List<Long> I need findItemByPIdEndDate() throws Exception {

                List<Long> list = null;

                try{
                        Session session = sessionFactory.getCurrentSession();

                        Query query = session.getNamedQuery("endDateChecker");
                        list =  query.list();

                        for(int i=0; i<list.size(); i++)
                        {
                                System.out.println(list.get(i));
                        }

                        System.out.println("Total " + list.size());

                }catch (HibernateException e){
                        throw new DataAccessException(e.getMessage());
                }

                return list;
        }

以下是我收到的异常消息:

Invocation of method 'findItemByPIdEndDate' on target class [class com.management.engine.Implementation] failed; nested exception is No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

到目前为止,我花了很多时间搜索我的方法,我试图修改我的方法:

 public List<Long> I need findItemByPIdEndDate() throws Exception {

                    List<Long> list = null;

                    try{
                            Session session = sessionFactory.openSession();

                            Query query = session.getNamedQuery("endDateChecker");
                            list =  query.list();

                            for(int i=0; i<list.size(); i++)
                            {
                                    System.out.println(list.get(i));
                            }

                            System.out.println("Total " + list.size());
                            session.close();
                    }catch (HibernateException e){
                            throw new DataAccessException(e.getMessage());
                    }

                    return list;
            }

我得到不同的错误信息,我得到:Invocation of method 'findItemByPIdEndDate' on target class [class com.management.engine.Implementation] failed; nested exception is could not execute query],任何人都知道这是什么,有什么建议吗?谢谢

我的queries.hbm.xml

<hibernate-mapping>

<sql-query name="endDateChecker">
<return-scalar column="PId" type="java.lang.Long"/>
      <![CDATA[select
   item_pid as PId
     from
         item
        where
        end_date < trunc(sysdate)]]>      
 </sql-query> 
</hibernate-mapping>

3 个答案:

答案 0 :(得分:5)

对于第二个错误(“无法执行查询”),我不知道,我真的想知道会话是什么样的。

在AFAIK中,持久化上下文不可用于Quartz Jobs,因为没有任何事情可以为它们建立一个Hibernate会话(Quartz在Servlet的上下文之外运行,而视图模式中的open会话在这里不适用)。这就是你得到第一个错误(“没有绑定到线程的hibernate会话”)的原因。

AOP – Spring – Hibernate Sessions for background threads / jobs中描述了一种解决方案。在这篇文章中,作者展示了如何使用Spring AOP代理来连接一个hibernate拦截器,它允许你访问持久化上下文,它负责关闭和打开你的会话

虽然没有自己测试,但它应该有用。

答案 1 :(得分:3)

我也面临同样的“ HibernateException:没有Hibernate Session绑定到线程”异常

2012-01-13 13:16:15.005 DEBUG MyQuartzJob Caught an exception 
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
at com.company.somemodule.dao.hibernate.AbstractHibernateDaoImpl.getSession(AbstractHibernateDaoImpl.java:107)
at com.company.somemodule.dao.hibernate.SomeDataDaoImpl.retrieveSomeData(SomeDataDaoImpl.java:264)

我按照示例here解决了这个问题。

相关代码

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import com.company.somemodule.dao.SomeDataDao;
import com.company.somemodule.SomeData;

public class MyQuartzJob extends QuartzJobBean implements Runnable {

  private boolean existingTransaction;
  private JobExecutionContext jobExecCtx;
  private static Logger logger = LoggerFactory.getLogger(MyQuartzJob.class);
  private SomeDataDao someDataDao; //set by Spring
  private Session session;
  private SessionFactory hibernateSessionFactory; //set by Spring

  protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException 
    this.jobExecCtx = ctx;
    run();
  }

  private void handleHibernateTransactionIntricacies() {
    session = SessionFactoryUtils.getSession(hibernateSessionFactory, true);
    existingTransaction = SessionFactoryUtils.isSessionTransactional(session, hibernateSessionFactory);
    if (existingTransaction) {
        logger.debug("Found thread-bound Session for Quartz job");
    } else {
        TransactionSynchronizationManager.bindResource(hibernateSessionFactory, new SessionHolder(session));
    }
  }


  private void releaseHibernateSessionConditionally() {
    if (existingTransaction) {
        logger.debug("Not closing pre-bound Hibernate Session after TransactionalQuartzTask");
    } else {
        TransactionSynchronizationManager.unbindResource(hibernateSessionFactory);
        SessionFactoryUtils.releaseSession(session, hibernateSessionFactory);
    }
  }

  @Override
  public void run() {
    // ..

    // Do the required to avoid HibernateException: No Hibernate Session bound to thread
    handleHibernateTransactionIntricacies();

    // Do the transactional operations
    try {

        // Do DAO related operations ..

    } finally {
        releaseHibernateSessionConditionally();
    }
  }

  public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {
    this.hibernateSessionFactory = hibernateSessionFactory;
  }

  public void setSomeDataDao(SomeDataDao someDataDao ) {
    this.someDataDao = someDataDao ;
  }
}

applicationContext.xml中的相关bean配置

<bean name="myJob" class="org.springframework.scheduling.quartz.JobDetailBean">  
  <property name="jobClass" value="com.somecompany.worker.MyQuartzJob" />
  <property name="jobDataAsMap">
    <map>
      <entry key="hibernateSessionFactory" value-ref="sessionFactory" />
      <entry key="someDataDao" value-ref="someDataDao" />
    </map>
  </property>
</bean>

答案 2 :(得分:0)

有虫虫https://jira.spring.io/browse/SPR-9020 还有解决方法。 使用此类配置具有hibernate.current_session_context_class属性的会话: https://gist.github.com/seykron/4770724