如何将http会话传递给DeferredResult?

时间:2017-09-04 15:40:35

标签: spring hibernate jackson threadpool lazy-evaluation

我有带有异步端点的Spring MVC应用程序:

@GetMapping
public DeferredResult<Collection<B>> get() {
    DeferredResult<Collection<B>> result = new DeferredResult<>();
    Executors.newSingleThreadExecutor().submit(() -> result.setResult(service.getB()));
    return result;
}

我尝试使用jackson-datatype-hibernate序列化惰性对象:

@Entity
@Table
public class B {

    @Id
    @GeneratedValue
    private UUID id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "a_id")
    private A a;

    public A getA() {
        return a;
    }
}

但我得到了:

Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.example.demo.B["a"])

1 个答案:

答案 0 :(得分:0)

我认为会话是指Hibernate会话而不是HTTP会话。

您的POJO(B)包含与A a映射的属性(FetchType.LAZY),因此当读取该属性时,Hibernate会话必须打开并且可用以满足偷懒。

我怀疑您正在打开每个调用会话的线程,并且由于响应是在另一个线程上处理的,因此在B被序列化的线程上Hibernate会话不可用。您必须将一些状态(可能通过创建可执行任务/运行程序)传递给创建延迟结果的线程,您可以在委派时将其扩展为包括当前打开的Hibernate会话(并记住在您拥有时关闭此会话)完成那个线程)。或者,您也可以:

  • 在创建延迟结果的线程上打开一个新的Hibernate会话
  • 更改FetchType,使其不再是懒惰。