Question

J'essaie d'invoquer une méthode basée sur un intervalle de temps, voici quelques beans dans applicationContext.xml

<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>

Voici la méthode que j'essaie d'invoquer:

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;
        }

Voici le message d'exception que je reçois:

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

J'ai passé beaucoup de temps à googler beaucoup jusqu'à présent et j'ai aussi essayé de modifier ma méthode comme ceci:

 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;
            }

Et j'obtiens un message d'erreur différent, je reçois: L'appel de la méthode 'findItemByPIdEndDate' sur la classe cible [class com.management.engine.Implementation] a échoué; exception imbriquée est impossible à exécuter requête] , tout le monde sait ce que c'est tout, des suggestions? merci

Aussi mes 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>
Était-ce utile?

La solution

Pour la deuxième erreur ("Impossible d'exécuter la requête"), je ne sais pas et je me demande vraiment à quoi ressemble une session.

En fait, autant que je sache, le contexte persistant n'est pas disponible pour Quartz Jobs, car rien ne permet de créer une session Hibernate pour eux (Quartz s'exécute en dehors du contexte des Servlets et le modèle de vue ouvert de la vue ne s'applique pas ici). C’est pourquoi vous obtenez la première erreur (" Aucune session d’hibernation liée au thread ").

Une solution à cela est décrite dans AOP - Spring - Hibernate Sessions pour les tâches / tâches en arrière-plan . Dans cet article, l'auteur montre comment vous pouvez utiliser les proxys Spring AOP pour câbler un intercepteur d'hibernation qui vous donne accès au contexte de persistance et prend soin de fermer et d'ouvrir les sessions pour vous .

Je n'ai pas testé moi-même, mais cela devrait fonctionner.

Autres conseils

Moi aussi, je faisais face au même " HibernateException: aucune session Hibernate liée au thread ". exception

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)

et je l'ai résolu en suivant l'exemple ici .

Code pertinent

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 ;
  }
}

Configuration du bean pertinente dans applicationContext.xml

<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>

Il y a un bogue au printemps https://jira.spring.io/browse/SPR-9020 Et il y a une solution de contournement. Configurez la session avec la propriété hibernate.current_session_context_class avec cette classe: https://gist.github.com/seykron/4770724

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top