Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate Spring ampq消费品-“;找不到当前线程的会话“;第一次尝试时出错_Hibernate_Spring Mvc_Transactions_Spring Transactions_Spring Amqp - Fatal编程技术网

Hibernate Spring ampq消费品-“;找不到当前线程的会话“;第一次尝试时出错

Hibernate Spring ampq消费品-“;找不到当前线程的会话“;第一次尝试时出错,hibernate,spring-mvc,transactions,spring-transactions,spring-amqp,Hibernate,Spring Mvc,Transactions,Spring Transactions,Spring Amqp,我有一个SpringMVC应用程序。我想使用springampq来执行异步任务。 我的REST后端使用@Transactional注释来管理事务。完成工作后,它将任务推送到呼气机,然后返回。然后,任务由使用者接收,使用者在第一次尝试时会收到“org.hibernate.HibernateException:No Session found for current thread”错误。然后spring ampq重试将任务发送给使用者,这次它可以正常工作,没有任何会话错误 我如何在第一次尝试时使此场

我有一个SpringMVC应用程序。我想使用springampq来执行异步任务。 我的REST后端使用@Transactional注释来管理事务。完成工作后,它将任务推送到呼气机,然后返回。然后,任务由使用者接收,使用者在第一次尝试时会收到“org.hibernate.HibernateException:No Session found for current thread”错误。然后spring ampq重试将任务发送给使用者,这次它可以正常工作,没有任何会话错误

我如何在第一次尝试时使此场景工作

我的spring ampq配置类似于此():

REST后端的代码与此类似:

@Controller
@Transactional(readOnly = true)
@RequestMapping(value = { "/myController" })
public class MyController extends BaseController {

    @Autowired
    private RabbitTemplate exchangeTemplate;

    @Transactional(readOnly = false)
    @RequestMapping(method = RequestMethod.POST)
    public @ResponseBody MyClass update(@RequestBody MyClass myclass, HttpServletRequest request) throws Exception {
        getAuthorizationManager().authorizeUserFromRequest(request);
        List<MyClass> result = getDataProvider().update(myclass);
        exchangeTemplate.convertAndSend("foo.Foo.update", myclass.getId())
        return result;
    }   
}
@控制器
@事务(只读=真)
@RequestMapping(值={“/myController”})
公共类MyController扩展BaseController{
@自动连线
私有RabbitTemplate交换模板;
@事务(只读=假)
@RequestMapping(method=RequestMethod.POST)
public@ResponseBody MyClass update(@RequestBody MyClass MyClass,HttpServletRequest)引发异常{
getAuthorizationManager().AuthorizationUserFromRequest(请求);
列表结果=getDataProvider().update(myclass);
exchangeTemplate.convertAndSend(“foo.foo.update”,myclass.getId())
返回结果;
}   
}

好的。现在我明白问题在哪里了。 您使用的是
LocalSessionFactoryBean
,它基于
SpringSessionContext
,反过来,它希望在
ThreadLocal
中的事务资源中有一个
SessionHolder
。但是,只要AMQP侦听器在自己的线程中工作,就没有任何钩子在事务资源中注册
sessionFactory
。类似于SpringMVC的OpenSessionInViewFilter

尝试使用

hibernate.current_session_context_class = local
作为
LocalSessionFactoryBean
hibernateProperties
。 我从未使用过
LocalSessionFactoryBean
。EE容器JNDI中的JTA
SessionFactory
始终适用于所有情况

更新:

好的,只要您可以使用MVC和AMQP Listener中相同的
IDataProvider
,问题就在于
CurrentSessionContext
,AMQP线程中没有
currentSession
,您必须执行
sessionFactory.openSession()
仅在
currentSessionContext
中没有
currentSession
的情况下,从
IDataProvider
实现的代码手动执行。大概是这样的:

Session hibernateSession = null;
try {
   hibernateSession = this.sessionFactory.getCurrentSession();
}
catch(HibernateException he) {
    hibernateSession = this.sessionFactory.openSession();
}
当然,您可以编写onw
SpringSessionContext
变量,并将该代码移动到
currentSession()

我不明白为什么在您重试的第二次尝试中它会起作用。在我的测试案例中,它无论如何都失败了

假设在您的配置中有一些东西,它负责处理
currentSession
,但您没有提到它


HTH

问题原来是在sessionfactory的初始化中。我有一个静态getDao函数,SessionFactory实例也是静态的:

@Repository
public class DaoFactory {

    private static SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        DaoFactory.sessionFactory = sessionFactory;
    }

    public static HibernateDaoBase getDao(Class<?> className) {
     .
     .

很抱歉,您尚未显示异常StackTrace。请加上你的听众的代码。也许没有理由添加
@Transactional
..@artem我已经用stacktrace错误和侦听器的代码更新了问题。如果没有
@Transactional
,所有尝试都会失败。我已经查看了“hibernate.current_session_context_class”属性,但它似乎“local”不是它的有效值:[。但我理解您试图表达的观点。我的一个问题是,我使用Tomcat作为服务器,直到现在还没有在其中设置事务管理器。[尽管如此,我还是不明白为什么会话在第二次试验中会被绑定。那么这不会也失败吗?这个线程建议不要使用当前的会话上下文类,除非你使用JTA,不幸的是,我不是。[是的,我理解这个问题。我认为只有一种方法可以解决它:实现您自己的拦截器,类似于
OpenSessionInViewInterceptor
,并将其与
@Transactional
一起使用。我不确定我是否能够管理它。据我所知,拦截器需要“在事务资源中注册
sessionFactory
“。我仍然无法理解为什么它在第二次尝试中注册,但在第一次尝试中没有注册。此外,由于OpenSessionInviewWinterCeptor是一个web请求拦截器,但这个新的拦截器不会,我需要熟悉AOP框架吗?不幸的是,我没有。
@Controller
@Transactional(readOnly = true)
@RequestMapping(value = { "/myController" })
public class MyController extends BaseController {

    @Autowired
    private RabbitTemplate exchangeTemplate;

    @Transactional(readOnly = false)
    @RequestMapping(method = RequestMethod.POST)
    public @ResponseBody MyClass update(@RequestBody MyClass myclass, HttpServletRequest request) throws Exception {
        getAuthorizationManager().authorizeUserFromRequest(request);
        List<MyClass> result = getDataProvider().update(myclass);
        exchangeTemplate.convertAndSend("foo.Foo.update", myclass.getId())
        return result;
    }   
}
hibernate.current_session_context_class = local
Session hibernateSession = null;
try {
   hibernateSession = this.sessionFactory.getCurrentSession();
}
catch(HibernateException he) {
    hibernateSession = this.sessionFactory.openSession();
}
@Repository
public class DaoFactory {

    private static SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        DaoFactory.sessionFactory = sessionFactory;
    }

    public static HibernateDaoBase getDao(Class<?> className) {
     .
     .
@Repository
public class DaoFactory {

    @Autowired
    private SessionFactory sessionFactory;

    public HibernateDaoBase getDao(Class<?> className) {
     .
     .
@Repository
@EnableCaching
public class DataProvider implements IDataProvider {

    @Autowired
    private DaoFactory daoFactory;