【问题标题】:Springboot - list of objects with child entities not returnedSpringboot - 未返回子实体的对象列表
【发布时间】:2022-01-13 18:55:38
【问题描述】:

我有一个名为 SubmittedQuiz 的对象,它由一个 Quiz 对象、User 对象和 submitQuestions 对象组成。

当我尝试执行此请求时:

GET http://localhost:8080/SubmittedQuiz/getForUser/10

我收到以下错误:

类型定义错误:[简单类型,类org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor];嵌套异常是 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties found to create BeanSerializer(为避免异常,禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过参考链:java.util.ArrayList[0]->edowl.Model.SubmittedQuiz["user"]->edowl.Model.User$HibernateProxy$lNsgwyQb["hibernateLazyInitializer"])"

请求很好地找到了对象,在设置断点时它实际上得到了对象列表,但是它在返回语句上失败了。

控制器方法如下图:

@GetMapping("/getForUser/{id}")
public ResponseEntity<List<SubmittedQuiz>> getSubmittedQuizForUser(@PathVariable("id") Long id){
    List<SubmittedQuiz> quizzes = submittedQuizService.findAllByUserId(id);
    return new ResponseEntity<>(quizzes, HttpStatus.OK); //ok is 200 status code
}

服务如下图所示:

public List<SubmittedQuiz> findAllByUserId(Long id) {
   return submittedQuizRepo.findAllByUserId(id);
}

回购如下图所示:

List<SubmittedQuiz> findAllByUserId(Long id);

SubmittedQuiz 如下图所示:

@Entity 
@Table(name = "Submitted_Quiz")
public class SubmittedQuiz {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(name = "User_Quiz_Submitted",
            joinColumns = { @JoinColumn(name = "quiz_submitted_id")},
            inverseJoinColumns = { @JoinColumn(name = "user_id")})
    public User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(name = "Quiz_Quiz_Submitted",
            joinColumns = { @JoinColumn(name = "quiz_submitted_id")},
            inverseJoinColumns = { @JoinColumn(name = "quiz_id")})
    public Quiz quiz;

    private float score;
    private LocalDate generatedDate;
    private float timeTaken;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "quiz_submitted_question",
            joinColumns = { @JoinColumn(name = "quiz_submitted_id")},
            inverseJoinColumns = { @JoinColumn(name = "question_id")})
    @Column(name = "submitted_questions")
    private Set<SubmittedQuestion> submittedQuestions = new HashSet<>();

我看到了一个关于在对象上添加 @JsonBackReference@JsonManagedReference 注释的建议。
但是到目前为止,我不需要在任何其他对象上执行此操作,并且到目前为止我使用的当前注释已经足够了

有什么建议吗?

【问题讨论】:

    标签: spring-boot spring-mvc jpa


    【解决方案1】:

    您可以尝试为此使用EntityGraph

    并设置为atributePaths所有具有FetchType.LAZY的实体:

    @EntityGraph(attributePaths = {"user", "quiz", "submitted_questions"})
    List<SubmittedQuiz> findAllByUserId(Long id);
    

    控制器的一些提示 - 你不需要直接设置 200 响应。默认返回状态码OK。所以以下会很好:

    @GetMapping("/getForUser/{id}")
    public List<SubmittedQuiz> getSubmittedQuizForUser(@PathVariable("id") Long id){
        return submittedQuizService.findAllByUserId(id);
    }
    

    更新:

    尝试添加 web 配置,例如::

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
        @Bean
        public Module datatypeHibernateModule() {
            return new Hibernate5Module();
        }
    }
    

    如果对解决错误问题没有帮助,请尝试添加:

    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

    致所有子实体:

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(...)
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    public User user;
    

    此外,JPA API 要求您的实体必须是可序列化的。 您必须按如下方式更新它:

    public class SubmittedQuiz implements Serializable {
        private static final long serialVersionUID = 1L;
    

    也为其他实体添加相同的内容(用户测验...)

    【讨论】:

    • 使用@entityGraph 时仍然存在错误
    • @ABpositive 更新了答案
    • @ABpositive 答案的哪一部分解决了问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 2013-05-01
    • 2015-11-23
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多