2012-04-24 21 views
20

im gettting el siguiente errorprimavera y de hibernación: No hay resultados para hilo actual Sesión

org.hibernate.HibernateException: No Session found for current thread 
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) 
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1024) 
at com.fexco.shoptaxfreemobile.service.ProfileService.registerVisitor(ProfileService.java:57) 
at com.fexco.shoptaxfreemobile.controller.ProfileController.registerVisitor(ProfileController.java:91) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213) 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578) 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923) 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852) 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at com.fexco.shoptaxfreemobile.jsonp.JsonpCallbackFilter.doFilter(JsonpCallbackFilter.java:33) 
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) 
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539) 
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300) 
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
at java.lang.Thread.run(Thread.java:619) 

La clase de servicio

@Service 
public class ProfileService { 

    @Resource(name = "mySessionFactory") 
    private SessionFactory sessionFactory; 

    @Autowired 
    private ProfileDao profileDao; 

    private class CountrySorter implements Comparator<Country> { 
     @Override 
     public int compare(Country country1, Country country2) { 
      if (country1.getId().compareTo(new Long (3)) < 0){ 
       return country1.getId().compareTo(country2.getId()); 
      } 
      return country1.getName().compareToIgnoreCase(country2.getName()); 
     }    
    } 

    public List<Country> getCountries() { 

     List<VisitorCountry> visitorCountries = profileDao.getAllCountries();  

     List<Country> countries = new ArrayList<Country>(); 
     for (VisitorCountry country : visitorCountries){ 
      countries.add(country.getCountry()); 
     } 

     Comparator<Country> comparator = new CountrySorter();  
     Collections.sort(countries, comparator); 

     return countries; 
    } 

    public RegisterResponse registerVisitor(JsonVisitor visitorDetails){ 
     Visitor storedVisitor = (Visitor) sessionFactory.getCurrentSession().get(Visitor.class, visitorDetails.getTfscNumber(), LockMode.NONE); 
     if (storedVisitor == null){ 
      storedVisitor = new Visitor(visitorDetails); 
     }else{ 
      storedVisitor.setVisitorDetails(visitorDetails);  
     } 

     try{ 
      sessionFactory.getCurrentSession().saveOrUpdate(storedVisitor); 

     }catch(Exception ex){ 
      return new RegisterResponse(false, "Failed To Register Card. Please Try Again Later.", visitorDetails); 
     } 

     return new RegisterResponse(true, "", visitorDetails); 

    } 
} 

poco de clase DAO

@Service 
@Transactional 
public class ProfileDao { 

    @Resource(name = "mySessionFactory") 
    private SessionFactory sessionFactory; 

    public List getAllCountries(){ 

     List<VisitorCountry> visitorCountries = sessionFactory.getCurrentSession() 
     .getNamedQuery("GET_ALL_COUNTRIES").list(); 

     return visitorCountries; 

    } 

    public List<Retailer> getRetailerByRetailerNumber(String retailerNo) { 

     List<Retailer> retailerByRetailerNumber = sessionFactory.getCurrentSession() 
     .getNamedQuery("FindRetailerByRetailerNo").setString("retailerNo", retailerNo).list(); 

     return retailerByRetailerNumber; 
    } 

y tengo esto en mi application-context.xml

<tx:annotation-driven transaction-manager="transactionManager"/> 

<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="myDataSource" /> 
    <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
    <property name="hibernateProperties"> 
     <value> 
      <![CDATA[ 
     hibernate.show_sql=true 
     hibernate.format_sql=true 
     hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider 
     ]]> 
     </value> 
    </property> 
</bean> 

¿Alguien puede detectar por qué me aparece el siguiente error?

+0

La respuesta de jordan002 es correcta, pero el problema "real" es que, en lugar de llamar a DAO en su servicio, está accediendo a DB desde la clase de servicio ... Por otro lado, normalmente desea que el método de servicio se comporte de forma transaccional en lugar de solo métodos DAO: si tiene 2 actualizaciones en el método de servicio y la segunda falla, las transacciones no le ayudan a tener DB coherente (pero depende de su lógica comercial) . – Betlista

Respuesta

40

Ha anotado su clase Dao con @Transactional, pero no su clase de servicio. La línea:

Visitor storedVisitor = 
    (Visitor) sessionFactory.getCurrentSession().get(Visitor.class, 
      visitorDetails.getTfscNumber(), LockMode.NONE); 

requiere una transacción.

Puede solucionar esto agregando la anotación @Transactional a su clase ProfileService, o solo el método registerVisitor().

+0

Esto va más allá y ayuda a que hibernate escriba actualizaciones/eliminaciones. – iowatiger08

5

cambio de su anotación DAO 's con @Repository

@Repository 
public class ProfileDao { 
. 
. 
. 
} 

y luego hacer que su método de servicio @Transactional por ejemplo como este

@Transactional 
public List<Retailer> getRetailerByRetailerNumber(String retailerNo) {} 
9

He resuelto el mismo problema con los pasos siguientes 2

  1. Colocado @Transactional en el método de servicio como se sugiere jordan002 en la respuesta en esta página.

  2. Una cosa más, si usted tiene 2 archivos de configuración: SAY application-context.xml (Para DB y contexto de aplicación de configuración específica ) y webmvc-context.xml (para web/controlador de configuración específica ), entonces usted debe escanear los paquetes diferentes para su controladores y dao.

    El webmvc-context.xml se carga después de application-context.xml. Creo que la clase DAO se carga primero con referencias transaccionales cuando se carga el application-context.xml, pero se reemplaza con otro objeto, sin referencias transaccionales, cuando se carga webmvc-context.xml.

    De cualquier manera, puedo solucionar el problema con paquetes específicos para analizar:

    <context:component-scan base-package="com.app.repository" /> 
    

    para application-context.xml

    y

    <context:component-scan base-package="com.app.web" /> 
    

    para webmvc-context.xml.

1

Sé que esto es una pregunta con cierta edad, pero me encontré con este tema y encontraron que si está utilizando la configuración de la primavera en Java, que una resolución tenía un par de partes de este. La colocación relativa de alguna configuración en el controlador fue importante.

primer lugar, el CoreConfiguration

@Configuration 
public class CoreConfiguration { 
@Bean   
public LocalSessionFactoryBean sessionFactory() { 
    LocalSessionFactoryBean factoryBean = new org.springframework.orm.hibernate4.LocalSessionFactoryBean(); 
    String annotatedPckgs[] ={"org.tigersndragons.reports.model.warehouse"}; 
    factoryBean.setAnnotatedPackages(annotatedPckgs);   
    Properties hibernateProperties = new Properties(); 
    try { 
     hibernateProperties.load(this.getClass().getResourceAsStream("props/hibernate.properties"));   
     factoryBean.setHibernateProperties(hibernateProperties); 
    } catch (IOException e) { } 
    factoryBean.setPackagesToScan("org.telligen.reports.model.warehouse"); 
    factoryBean.setDataSource(warehouseDataSource());//("jdbc/warehouse"); 
    try { 
     factoryBean.afterPropertiesSet(); 
    } catch (IOException e) {  } 
    return factoryBean; 
} 
@Bean 
public WarehouseDAO getWarehouseDAO(){ 
    WarehouseDAO wrhsDao = new WarehouseDAO(); 
    wrhsDao.setSessionFactory(sessionFactory().getObject()); 
    return wrhsDao; 
} 

...

@Configuration 
public class ScheduleConfiguration { 
private static Logger logger = LoggerFactory.getLogger(ScheduleConfiguration.class); 

@Autowired 
private CoreConfiguration coreConfiguration; 


@Bean 
public HandlerMapping handlerMapping(){ 
    DefaultAnnotationHandlerMapping mapping = new DefaultAnnotationHandlerMapping(); 
    mapping.setInterceptors(new Object []{coreConfiguration.openSessionViewInterceptor()}); 
    return mapping; 
} 

@Bean 
public HandlerAdapter handerAdapter(){ 
    return new AnnotationMethodHandlerAdapter(); 
} 

@Bean 
public ScheduleController scheduleController() throws Exception{ 
    ScheduleController controller = new ScheduleController(); 
     controller.setWrhsDao(coreConfiguration.getWarehouseDAO()); 
    return controller; 
} 

... 

en el controlador, que tenía que establecer

@Controller 
@RequestMapping 
public class ScheduleController { 
private static Logger logger = LoggerFactory.getLogger(ScheduleController.class); 

private WarehouseDAO wrhsDao; 
    @RenderMapping 
@RequestMapping("VIEW") 
public String viewSchedule(Map<String, Object> modelMap){...} 

public void setWrhsDao(WarehouseDAO wrhsDao) { 
    this.wrhsDao = wrhsDao; 
} 
} 

El WarehouseDAO tiene la anotación @Repository y la SessionFactory no fue Autowired.

Espero que esto ayude a alguien más con preguntas similares.

0

Voy a agregar algo que me llevó un tiempo depurar: no olvide que una anotación @Transactional solo funcionará en métodos "públicos".

Puse algunos @Transactional en los "protegidos" y obtuve este error.

espero que ayude :)

http://docs.spring.io/spring/docs/3.1.0.M2/spring-framework-reference/html/transaction.html

visibilidad Método y @Transactional

Al utilizar servidores proxy, debe solicitar la anotación @Transactional sólo para métodos con visibilidad pública. Si anota protegidos, métodos privados o visibles con el paquete con la anotación @Transactional, , no se produce ningún error, pero el método anotado no muestra la configuración transaccional configurada . Considere el uso de AspectJ (consulte a continuación) si necesita anotar métodos no públicos.

2

I resuelto el problema anteriormente siguiendo dos pasos

1-Adición de apoyo @Transactional en mi método de servicio que está llamando métodos DAO

2-importando el applicationContext.xml en primavera-servlet .xml de esta manera

<import resource="applicationContext.xml" /> 

<mvc:annotation-driven /> 
<context:component-scan base-package="com.json.api.*" /> 
<!--Third Party Integration should be injected in xml start here --> 
    <bean id="integrationInterface" class="com.json.api.IntegerationInterface"></bean> 
<!--Third Party Integration should be injected in xml start here --> 
<mvc:interceptors> 
    <bean id="apiServiceInterceptor" class="com.json.api.interceptor.ApiServiceInterceptor"></bean> 
</mvc:interceptors> 
<!--To Enable @Value to map key with provided fields for property files --> 
<context:property-placeholder /> 

Se elimina la necesidad de escanear paquete edades en dos lugares spring-servlet.xml y applicationContext.xml

Cuestiones relacionadas