Spring and hibernate: No Session found for current thread

故事扮演 提交于 2019-11-26 22:33:12
Peter Bratton

You annotated your Dao class with @Transactional, but not your service class. The line:

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

requires you to be in a transaction.

You can fix this by adding the @Transactional annotation to your ProfileService class, or just the registerVisitor() method.

I solved the same problem with following 2 steps

  1. Placed @Transactional on the service method as suggested jordan002 in his answer on this page.

  2. One more thing,If you have 2 configuration files: say application-context.xml(For DB and Application Context Specific configuration) and webmvc-context.xml(For web/controller specific configuration), then you should scan the packages different for your controllers and dao.

    The webmvc-context.xml is loaded after application-context.xml. I think the DAO class is loaded first with transactional references when the application-context.xml is loaded, but it is replace with another object, without transactional references, when webmvc-context.xml is loaded.

    Any way, I resolve the problem with specific packages scanned:

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

    for application-context.xml

    and

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

    for webmvc-context.xml.

change your DAO 's annotation with @Repository

@Repository
public class ProfileDao { 
.
.
.
}

and then make your service method @Transactional for example like this

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

I solved the above problem by following two step

1-Adding @Transactional support in my service method which is calling DAO methods

2-By importing the applicationContext.xml in spring-servlet.xml in this way

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

It removes the need to scan packages in two places spring-servlet.xml and applicationContext.xml

I know this is an question with some age, but I ran into this issue and found that if you are using Spring-Java configuration, that a resolution had a couple parts to this. Relative placement of some configuration to the controller was important.

First, the 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;
}

 ...

In the Controller, I had to set

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

The WarehouseDAO has the @Repository annotation and the SessionFactory was not Autowired.

Hope this helps someone else with similar questions.

I'll just add something that took me some time to debug : don't forget that a @Transactional annotation will only work on "public" methods.

I put some @Transactional on "protected" ones and got this error.

Hope it helps :)

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

Method visibility and @Transactional

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!