Domanda

Sto cercando di invocare il metodo basato su un intervallo di tempo, qui ci sono alcuni bean all'interno di 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>

Ecco il metodo che sto cercando di invocare:

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

Ecco il messaggio di eccezione che ricevo:

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

Finora ho passato molto tempo a cercare su google anche io ho provato a modificare il mio metodo in questo modo:

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

E ricevo un messaggio di errore diverso, ottengo: Invocazione del metodo 'findItemByPIdEndDate' sulla classe di destinazione [class com.management.engine.Implementation] non riuscita; l'eccezione nidificata non è in grado di eseguire la query] , qualcuno sa di cosa si tratta, qualche suggerimento? grazie

Anche le mie 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>
È stato utile?

Soluzione

Per il secondo errore (" impossibile eseguire la query "), non lo so e mi chiedo davvero come sia la sessione.

In realtà, AFAIK, il contesto persistente non è disponibile per Quartz Jobs poiché nulla si occupa di stabilire una Sessione di ibernazione per loro (Quartz scorre al di fuori del contesto di Servlet e la sequenza aperta nella vista non si applica qui). Questo è il motivo per cui ricevi il primo errore (" Nessuna sessione di ibernazione associata al thread ").

Una soluzione per questo è descritta in AOP - Spring - Hibernate Session per thread / processi in background . In questo post, l'autore mostra come puoi usare i proxy Spring AOP per collegare un intercettore in letargo che ti dà accesso al contesto di persistenza e si prende cura di chiudere e aprire le sessioni per te .

Non l'ho provato io stesso, ma dovrebbe funzionare.

Altri suggerimenti

Anch'io stavo affrontando lo stesso " HibernateException: nessuna sessione di ibernazione legata al thread " eccezione

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)

e l'ho risolto seguendo l'esempio qui .

Codice rilevante

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

Configurazione del bean rilevante all'interno di 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>

C'è primavera di bug https://jira.spring.io/browse/SPR-9020 E c'è una soluzione alternativa. Configurare la sessione con la proprietà hibernate.current_session_context_class con questa classe: https://gist.github.com/seykron/4770724

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top