当前位置: 首页 > 知识库问答 >
问题:

Spring JPA延迟加载-无法初始化代理

景英杰
2023-03-14

以下是一些背景代码:

InitiativeProfileQuestion。java:

@Entity
@Table
public class InitiativeProfileQuestion implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(nullable = false)
    private String question;

    @Column
    private String description;

    @Column
    private int sortOrder;

    @OneToMany(mappedBy = "initiativeProfileQuestion", fetch = FetchType.LAZY)
    private List<InitiativeProfileAnswer> answers;

    public List<InitiativeProfileAnswer> getAnswers() {
        return answers;
    }

    public void setAnswers(List<InitiativeProfileAnswer> answers) {
        this.answers = answers;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(int sortOrder) {
        this.sortOrder = sortOrder;
    }

}

ProfileAnswer.java:

@Entity
@Table
public class InitiativeProfileAnswer {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column
    private String answer;

    @Column
    private int sortOrder;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "initiativeProfileQuestionId")
    @JsonIgnore
    private InitiativeProfileQuestion initiativeProfileQuestion;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getAnswer() {
        return answer;
    }

    public void setAnswer(String answer) {
        this.answer = answer;
    }

    public int getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(int sortOrder) {
        this.sortOrder = sortOrder;
    }

    public InitiativeProfileQuestion getInitiativeProfileQuestion() {
        return initiativeProfileQuestion;
    }

    public void setInitiativeProfileQuestion(InitiativeProfileQuestion initiativeProfileQuestion) {
        this.initiativeProfileQuestion = initiativeProfileQuestion;
    }
}

InitiativeProfileQuestionRepository。java:

public interface InitiativeProfileQuestionRepository extends JpaRepository<InitiativeProfileQuestion, Long> {

    @Query("select ipa from InitiativeProfileQuestion ipa join fetch ipa.answers")
    public List<InitiativeProfileQuestion> getAllQuestions();
}

InitiativeProfileService。java:

@Service
public class InitiativeProfileService {

    @Autowired
    private InitiativeProfileQuestionRepository initiativeProfileQuestionRepository;

    public List<InitiativeProfileQuestion> getAllQuestions() {
        return initiativeProfileQuestionRepository.findAll();
    }

    public List<InitiativeProfileQuestion> getAllQuestionsFetch() {
        return initiativeProfileQuestionRepository.getAllQuestions();
    }

}

基础ontroller.java:

@RestController
@RequestMapping("/api")
public class BaseController {

    @Autowired
    InitiativeProfileService initiativeProfileService;

    @RequestMapping("/question")
    public List<InitiativeProfileQuestion> getQuestions() {
        return initiativeProfileService.getAllQuestions();
    }

    @RequestMapping("/questionFetch")
    public List<InitiativeProfileQuestion> getQuestionsFetch() {
        return initiativeProfileService.getAllQuestionsFetch();
    }
}

在我的BaseController中调用get问题()会返回“无法初始化代理-没有会话”错误。但是,在我的BaseController中调用get问卷Fetch()可以很好地加载。

我希望它的工作方式是,如果调用getQuestions(),则返回的对象将没有答案(因为延迟加载的对象不会在任何地方调用)。然而,这只是给了我一个错误。如果我使用连接获取进行查询,它也会显示答案(预期行为)。

我做错了什么?我在不同的地方尝试了@Transactional,但没有成功。我也没有。xml文件—到目前为止,所有操作都是使用注释完成的。

我得到的错误是:

exception

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"])
    org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101)
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:185)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
root cause

com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"])
    com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:210)
    com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:177)
    com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:187)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:647)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:558)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:145)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
    com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
    com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:128)
    com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1902)
    org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101)
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:185)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

共有2个答案

景麒
2023-03-14

正如您从stacktrac中看到的,错误发生在Jackson试图访问延迟加载的对象以便将其序列化为JSON时。此时,Spring事务已经完成,Hibernate会话关闭,这就是为什么Hibernate不能再加载该对象。

如果不打算序列化该字段,则可能希望使用@JsonIgnore或Spring的Jackson序列化视图支持。

汪信鸥
2023-03-14

对于延迟加载情况下的异常,您必须尝试在会话外部获取关联对象。将延迟加载更改为“渴望”,或者将获取关联对象的代码放在会话中。例如:

    public void test() {

            Session session = HibernateUtil.currentSession();
            session.beginTransaction();

            Vehicle  vehicle= (Vehicle) session.get(Vehicle.class, 2);

            System.out.println(vehicle.getVehicleName());

            session.getTransaction().commit();
            session.close();
            System.out.println(vehicle.getVehicleName()); //No exception here
            System.out.println(vehicle.getUser().getUserName()); 
// Exception here change the loading to EAGER or put this line of code within the session above. Put it before session.close() or  before session.getTransaction().commit();
        }
 类似资料:
  • 我在我的WordPress网站上使用JetPack,并启用了延迟加载。然而,在我的网站中,我用AJAX更新了一些内容,这导致加载1x1占位符的图像,而不是真正的图像,这是懒惰加载会处理的。 如何使用Jet Pack再次调用延迟加载?我似乎记得有一个JavaScript函数,但找不到它是什么。

  • 我有一个应用程序,我正在扩展它以提供REST API。在主站点中一切正常,但当我尝试访问REST API时,我在异常日志中得到以下内容: 禁用延迟加载将解决此问题,但会导致不可接受的性能(加载时间从 200 毫秒到 22 秒)。我不知道如何处理这个问题。 我刚开始在ColdFusion中Rest,在我看来,CFC正在以一种不寻常的方式被处理。它们似乎没有被初始化(init方法似乎没有运行),现在看

  • 我正在使用JPA(Hibernate 4 . 3 . 3作为持久性提供者)和Spring (3.2.2),我所有的字段都加载得很好,但是当我试图访问我的集合时,它抛出了错误- 当我调试这个时,我的实体类中定义的每个集合都有错误- 我尝试使用collection.size()和Hibernate.initialize(),但都不起作用。在Internet上搜索时,我发现扩展Persitence将解决

  • 我正在制作一个网站,我试图在其中订购配料。我选择配料并输入其数量,然后单击添加。我重复了几次。然后我进入下一页,在其中我选择了一个供应商。然后我按“订单”。 预计将Nabavka插入数据库并打开一个页面,说明订单成功,但我收到一个异常,告诉我不能懒惰地初始化它。 来自NabavkaController。java: Nabavka.java: 纳米尔尼卡。java: 纳巴夫卡科帕。java: 纳巴夫

  • 我不明白为什么会发生这种情况。根据代码路径,当引发此异常时,我应该在同一线程中并且会话应存在。 有人能告诉我我错过了什么吗? 我有设置 在hibernate.cfg.xml档案里 我在Servlet过滤器中创建了以下代码 在index.xhtml文件中,我有以下调用: 做一些事情 index.xhtml正在使用使用ui include加载menu.xhtml文件的模板。然后,菜单文件会插入menu

  • 问题内容: 我使用休眠来创建一个REST API。我创建了一种获取表中所有项目的方法。 这是我的Language.java 这是我的Patient.java 重要提示:Bean和映射是通过NetBeans从MySQL数据库反向工程的。调用时,不需要获取任何与之相关的数据。我的表格只有2列,而。表的前键为 在rest api中使用此方法之前,它没有任何异常即可完美运行。但是,当我在rest api中