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

Spring和hibernate:未找到当前线程的会话,spring,hibernate,sessionfactory,Spring,Hibernate,Sessionfactory,我发现以下错误 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(Sessi

我发现以下错误

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

    }
}
@服务
公共类档案服务{
@资源(name=“mySessionFactory”)
私人会话工厂会话工厂;
@自动连线
私有ProfileDao ProfileDao;
私有类CountrySorter实现比较器{
@凌驾
公共整数比较(国家/地区1、国家/地区2){
if(country1.getId().compareTo(新长(3))<0){
返回country1.getId().compareTo(country2.getId());
}
返回country1.getName().compareToIgnoreCase(country2.getName());
}               
}
国家/地区公共列表(){
List visitorCountries=profileDao.getAllCountries();
列表国家=新的ArrayList();
for(访问者国家/地区:访问者国家/地区){
countries.add(country.getCountry());
}
比较器比较器=新CountrySorter();
集合。排序(国家、比较国);
返回国;
}
公共注册表响应注册表服务器(JsonVisitor VISITOR详细信息){
Visitor storedVisitor=(Visitor)sessionFactory.getCurrentSession().get(Visitor.class,visitorDetails.getTfscNumber(),LockMode.NONE);
if(storedVisitor==null){
storedVisitor=新访客(访客详细信息);
}否则{
storedVisitor.setVisitorDetails(visitorDetails);
}
试一试{
sessionFactory.getCurrentSession().saveOrUpdate(storedVisitor);
}捕获(例外情况除外){
返回新的RegisterResponse(false,“注册卡失败。请稍后重试。”,visitorDetails);
}
返回新的RegisterResponse(true,“,visitorDetails);
}
}
刀类之位

@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;
    }
@服务
@交易的
公共类配置文件{
@资源(name=“mySessionFactory”)
私人会话工厂会话工厂;
公共列表getAllCountries(){
List visitorCountries=sessionFactory.getCurrentSession()
.getNamedQuery(“获取所有国家/地区”).list();
回访国家;
}
公共列表getRetailerByRetailerNumber(字符串retailerNo){
List retailerByRetailerNumber=sessionFactory.getCurrentSession()
.getNamedQuery(“FindRetailerByRetailerNo”).setString(“retailerNo”,retailerNo).list();
返回retailerByRetailerNumber;
}
我的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>


有人知道我为什么会出现以下错误吗?

您用@Transactional注释了Dao类,但没有注释服务类。行:

Visitor storedVisitor =
    (Visitor) sessionFactory.getCurrentSession().get(Visitor.class,
            visitorDetails.getTfscNumber(), LockMode.NONE);
要求您参与交易


您可以通过将@Transactional注释添加到ProfileService类,或者只添加registerVisitor()方法来解决此问题。

使用@Repository更改DAO的注释

@Repository
public class ProfileDao { 
.
.
.
}
然后将您的服务方法@Transactional设置为如下所示

@Transactional
public List<Retailer> getRetailerByRetailerNumber(String retailerNo) {}
@Transactional
公共列表getRetailerByRetailerNumber(字符串retailerNo){}

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

  • 按建议将
    @Transactional
    放置在服务方法上 jordan002在本页的回答中

  • 还有一件事,如果你有两个配置文件:比如
    application context.xml
    (用于特定于数据库和应用程序上下文的 配置)和
    webmvc context.xml
    (用于特定于web/controller的 配置),然后您应该为您的应用程序扫描不同的包 控制器和dao

    webmvc context.xml
    application context.xml
    之后加载。 我认为DAO类首先加载事务引用 加载application-context.xml,但将其替换为 另一个对象,没有事务引用,当 已加载webmvc-context.xml

    无论如何,我都可以通过扫描特定的包来解决问题:

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


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

    首先,核心配置

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

    在控制器中,我必须设置

    @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;
    }
    }
    
    @控制器
    @请求映射
    公共类调度控制器{
    私有静态记录器Logger=LoggerFactory.getLogger(ScheduleController.class);
    私人仓库;
    @渲染映射
    @请求映射(“视图”)
    公共字符串viewSchedule(映射模型映射){…}
    公共无效setWrhsDao(仓库道wrhsDao){
    this.wrhsDao=wrhsDao;
    }
    }
    
    WarehouseDAO具有@Repository注释,并且SessionFactory未自动连接


    希望这能帮助其他人解决类似的问题。

    我将添加一些花了我一些时间调试的内容:不要忘记@Transactional注释只适用于“public”方法

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

    希望有帮助:)

    方法可见性和@Transactional

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


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

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

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

    它消除了在两个地方扫描包的需要。
    @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;
    }
    }
    
     <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 />