spring Spring和hibernate:未找到当前线程的会话

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10298483/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:05:59  来源:igfitidea点击:

Spring and hibernate: No Session found for current thread

springhibernatesessionfactory

提问by Hip Hip Array

im gettting the following error

我收到以下错误

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)

Service class

服务类

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

    }
}

bit of DAO class

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

and i have this in my application-context.xml

我在我的 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>

can anyone spot why i am getting the following error?

谁能发现为什么我收到以下错误?

回答by Peter Bratton

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

您使用 @Transactional 注释了 Dao 类,而不是您的服务类。线路:

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.

您可以通过向 ProfileService 类添加 @Transactional 注释或仅添加 registerVisitor() 方法来解决此问题。

回答by Arun Kumar

I solved the same problem with following 2 steps

我通过以下两个步骤解决了同样的问题

  1. Placed @Transactionalon the service method as suggested jordan002in 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.xmlis 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.

  1. @Transactional按照jordan002在此页面上的回答中的建议放置在服务方法 上。

  2. 还有一件事,如果您有 2 个配置文件:例如 application-context.xml(对于 DB 和应用程序上下文特定配置)和webmvc-context.xml(对于 Web/控制器特定配置),那么您应该扫描控制器和 dao 的不同包。

    webmvc-context.xml后载入application-context.xml。我认为在加载 application-context.xml 时首先使用事务引用加载 DAO 类,但是当加载 webmvc-context.xml 时,它会替换为另一个没有事务引用的对象。

    无论如何,我解决了扫描特定包的问题:

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

    为了 application-context.xml

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

    webmvc-context.xml

回答by erimerturk

change your DAO 's annotation with @Repository

使用 @Repository 更改您的 DAO 的注释

@Repository
public class ProfileDao { 
.
.
.
}

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

然后让你的服务方法 @Transactional 像这样

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

回答by pintu

I solved the above problem by following two step

我通过以下两步解决了上述问题

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

1-在我调用 DAO 方法的服务方法中添加 @Transactional 支持

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

2-通过这种方式在spring-servlet.xml中导入applicationContext.xml

 <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

它消除了在 spring-servlet.xml 和 applicationContext.xml 两个地方扫描包的需要

回答by iowatiger08

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.

我知道这是一个有些年头的问题,但我遇到了这个问题并发现如果您使用的是 Spring-Java 配置,那么解决方案有几个部分。某些配置与控制器的相对位置很重要。

First, the CoreConfiguration

一、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.

WarehouseDAO 有 @Repository 注释,SessionFactory 没有自动装配。

Hope this helps someone else with similar questions.

希望这可以帮助其他有类似问题的人。

回答by lboix

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.

我将添加一些花了我一些时间来调试的东西:不要忘记 @Transactional 注释仅适用于“公共”方法。

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

我把一些@Transactional 放在“受保护的”上,并得到了这个错误。

Hope it helps :)

希望能帮助到你 :)

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

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.

方法可见性和@Transactional

使用代理时,您应该仅将 @Transactional 注释应用于具有公共可见性的方法。如果您使用 @Transactional 注释对受保护的、私有的或包可见的方法进行注释,则不会引发错误,但带注释的方法不会显示配置的事务设置。如果您需要注释非公共方法,请考虑使用 AspectJ(见下文)。