Pregunta

Estoy tratando de invocar un método basado en un intervalo de tiempo, aquí hay algunos beans dentro de 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>

Aquí está el método que intento invocar:

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

Aquí está el mensaje de excepción que recibo:

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

He pasado mucho tiempo buscando en Google hasta ahora y también he tratado de modificar mi método de esta manera:

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

Y obtengo un mensaje de error diferente, obtengo: La invocación del método 'findItemByPIdEndDate' en la clase de destino [clase com.management.engine.Implementation] falló; excepción anidada no se pudo ejecutar la consulta] , alguien sabe de qué se trata, ¿alguna sugerencia? gracias

También mis consultas.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>
¿Fue útil?

Solución

Para el segundo error (" no se pudo ejecutar la consulta "), no sé y realmente me pregunto qué aspecto tendrá la sesión.

De hecho, AFAIK, el contexto persistente no está disponible para Quartz Jobs ya que nada se encarga de establecer una sesión de Hibernate para ellos (Quartz se ejecuta fuera del contexto de Servlets y el patrón de sesión abierta en vista no se aplica aquí). Es por eso que obtiene el primer error (" Ninguna sesión de hibernación vinculada al hilo ").

Una solución para esto se describe en AOP & # 8211; Primavera & # 8211; Sesiones de hibernación para subprocesos / trabajos en segundo plano . En esta publicación, el autor muestra cómo puede usar los proxies Spring AOP para conectar un interceptor de hibernación que le da acceso al contexto de persistencia y se encarga de cerrar y abrir las sesiones para usted .

Sin embargo, no lo probé yo mismo, pero debería funcionar.

Otros consejos

Yo también me enfrentaba a la misma " HibernateException: no hay sesión de Hibernate vinculada al hilo " excepción

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)

y lo resolví siguiendo el ejemplo aquí .

Código relevante

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

Configuración de bean relevante dentro de 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>

Hay un error de primavera https://jira.spring.io/browse/SPR-9020 Y hay una solución alternativa. Configure la sesión con la propiedad hibernate.current_session_context_class con esta clase: https://gist.github.com/seykron/4770724

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top