Spring 如何将Hibernate会话与JmsListener方法关联

Spring 如何将Hibernate会话与JmsListener方法关联,spring,hibernate,spring-data,lazy-loading,spring-jms,Spring,Hibernate,Spring Data,Lazy Loading,Spring Jms,我有一个SpringBoot应用程序,它使用SpringData在Oracle数据库上保存数据,并使用springbootstarteractivemq处理JMS队列 我正在公开一个DELETErestwebservice,这需要一些时间。我不想让我的用户挂断响应 因此,我添加了一个用@JmsListener注释的方法来完成这项工作,并用jmsTemplate.convertAndSend()调用它 但是,如果我处理的findAll()部分工作正常,只要我试图访问使用findAll()方法检索的

我有一个
SpringBoot
应用程序,它使用
SpringData
在Oracle数据库上保存数据,并使用
springbootstarteractivemq
处理JMS队列

我正在公开一个
DELETE
restwebservice,这需要一些时间。我不想让我的用户挂断响应

因此,我添加了一个用
@JmsListener
注释的方法来完成这项工作,并用
jmsTemplate.convertAndSend()调用它

但是,如果我处理的
findAll()
部分工作正常,只要我试图访问使用
findAll()
方法检索的数据(例如,简单地显示数据),我就面临着惰性集合的
LazyLoadingException
,说我没有Hibernate会话。
org.hibernate.LazyInitializationException:未能延迟初始化角色集合:…,无法初始化代理-无会话

以下是我的代码片段,如果有帮助的话:

   public void myMethod(int batchSize) {
    // Send a JMS message with a POJO
    LOGGER.trace("Calling JMS method...");
    final JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
    jmsTemplate.convertAndSend("runJob", batchSize);
}

@JmsListener(destination = "runJob")
private void runJob(final int batchSize) {
    LOGGER.debug("Calling runJob with batchSize {}", batchSize);
    List<MyEntity> myEntities = myRepository.findAll();
    LOGGER.debug("{} entities retrieved from the DB", myEntities.size()); // Prints the actual number of entities in my DB
    for(Entity entity : entities){
        LOGGER.debug("Entity name {}", entity.getName()); // Prints entity name
        LOGGER.debug("Entity first collection's value {}", entity.getMyList().get(0).toString()); // org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session
    }
}

// -----------------------
// Full code of my repository -> The implementation is generated by spring-data http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
public interface MyRepository extends org.springframework.data.jpa.repository.JpaRepository<MyEntity, Long>{}
public void myMethod(int batchSize){
//使用POJO发送JMS消息
trace(“调用JMS方法…”);
final JmsTemplate JmsTemplate=context.getBean(JmsTemplate.class);
convertAndSend(“runJob”,batchSize);
}
@JmsListener(destination=“runJob”)
专用void运行作业(最终int batchSize){
debug(“使用batchSize{}调用runJob”,batchSize);
List myEntities=myRepository.findAll();
LOGGER.debug(“{}从数据库检索到的实体”,myEntities.size());//打印我的数据库中实体的实际数量
for(实体:实体){
LOGGER.debug(“实体名称{}”,Entity.getName());//打印实体名称
LOGGER.debug(“实体第一个集合的值{}”,Entity.getMyList().get(0).toString());//org.hibernate.LazyInitializationException:未能延迟初始化角色的集合:…,无法初始化代理-无会话
}
}
// -----------------------
//my repository的完整代码->实现由spring数据生成http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-方法.查询创建
公共接口MyRepository扩展了org.springframework.data.jpa.repository.JpaRepository{}
我只是想知道如何将会话连接到Jms方法

干杯,
Olivier

您的
JmsListener
方法是异步处理的(这就是为什么要这样做的原因),因此它运行在不同的线程上。如果它运行在不同的线程上,则不能使用同一事务


但是,您可以在处理JMS消息时启动一个新事务,但您必须了解这具体意味着什么。在
runJob
上添加
@Transactional
就可以了。因为它现在是异步的,所以您必须在响应中考虑到这一点。您将返回什么HTTP状态代码。例如,在后台可能会出现故障

不要描述您的代码和异常。发布它们。@JBNizet只是添加了一个代码段。顺便说一句,异常列在我的初始帖子(LazyLoadingException在我的惰性集合上)中,代码(显示数据)也在那里。我想我可以专注于真正重要的东西:问题,而不是纯粹的代码。不管怎样,给你。谢谢你的回复。关于异步进程的目标,我100%同意你的看法。当然,我肯定不会让
runJob
myMethod
在同一事务中运行。我只想
runJob
在调用
myRepository.findAll()
后不要关闭Hibernate会话。我忘了提到它,但是是的,我试图使
runJob
@Transactional
,但没有成功。像你一样,我想它也能做到。。。我不明白如果一个方法在运行时关闭了它的
会话
,它怎么会是
@Transactional
。。。顺便说一句,我还有一些代码,这样人们就可以知道JMS方法已经做了什么。您的方法是私有的,它必须是公共的,以便为事务目的代理它。实际上,我对
@JmsListener
的私人作品感到惊讶,很抱歉,但这并不能解决问题。我肯定会的,但是。。。我仍然面临着完全相同的问题,尽管我将所有方法
公开了
。恐怕我无法帮助您处理部分代码片段。代码中还有其他东西使它失败,但我不知道是什么。你能分享一个样品吗?好的。我必须创建另一个项目,然后。我当然不能分享我的整个项目。顺便说一句,我正计划这样做以隔离问题。我只是需要一些时间来做这个。。。我会尽我最大的努力尽快创造。