首页 > 解决方案 > FetchType.LAZY 不显示外键列

问题描述

我尝试将 FetchType.LAZY 与 Spring Boot 一起使用。但是,为什么即使执行的查询是选择 FK 列,FK 列也不显示在 JSON 中?这是我在控制台中打印的模型、控制器、存储库和执行的查询,以及邮递员中的 JSON 结果

// AnswerModel
@Entity
@Table(name = "answers")
public class Answer implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String text;
    private Question question;
    private Date createdAt;
    private Date updatedAt;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "question_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    public Question getQuestion() {
        return question;
    }

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

// others getter and setter
}

// QuestionModel
@Entity
@Table(name = "questions")
public class Question implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String title;
    private String description;
    private Date createdAt;
    private Date updatedAt;

    // getters and setters
}

// AnswerController
@GetMapping("/answers")
    public List<Answer> getAllAnswer(){
        return answerRepository.findAll();
    }

// AnswerRepository
@Repository
@Transactional
public interface AnswerRepository extends JpaRepository<Answer, Long> {
}

// Query that executed when API hit in the postman
select
        answer0_.id as id1_0_,
        answer0_.created_at as created_2_0_,
        answer0_.question_id as question5_0_,
        answer0_.text as text3_0_,
        answer0_.updated_at as updated_4_0_ 
    from
        answers answer0_

// output JSON in postman (it did not show the question id, but the query did select the question_id column)
[
    {
        "id": 1,
        "text": "Please look into this github",
        "createdAt": "2018-11-22T03:55:48.865+0000",
        "updatedAt": "2018-11-22T03:55:48.865+0000"
    },
    {
        "id": 2,
        "text": "Please watch my youtube channel",
        "createdAt": "2018-11-22T03:55:57.642+0000",
        "updatedAt": "2018-11-22T03:55:57.642+0000"
    }
]

那么,这里出了什么问题?如何显示 question_id?这个答案真的值得推荐吗?Hibernate - 外键而不是实体

更新

这是最新的代码,但根据@Markoorn 的回答,我仍然无法弄清楚我必须在哪里调用 answer.getQuestion();

// AnswerModel
@Entity
@Table(name = "answers")
public class Answer implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String text;
    private Question question;
    private Date createdAt;
    private Date updatedAt;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "question_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    public Question getQuestion() {
        return question;
    }

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

// others getter and setter
}

// QuestionModel
@Entity
@Table(name = "questions")
public class Question implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String title;
    private String description;
    private Date createdAt;
    private Date updatedAt;

    // getters and setters
}

// AnswerController
@Transactional
@GetMapping("/answers")
    public List<Answer> getAllAnswer(){
        return answerRepository.findAll();
    }

// AnswerRepository
@Repository
@Transactional
public interface AnswerRepository extends JpaRepository<Answer, Long> {
}

// Query executed
Hibernate: 
    select
        answer0_.id as id1_0_,
        answer0_.created_at as created_2_0_,
        answer0_.question_id as question5_0_,
        answer0_.text as text3_0_,
        answer0_.updated_at as updated_4_0_ 
    from
        answers answer0_
Hibernate: 
    select
        question0_.id as id1_1_0_,
        question0_.created_at as created_2_1_0_,
        question0_.description as descript3_1_0_,
        question0_.title as title4_1_0_,
        question0_.updated_at as updated_5_1_0_ 
    from
        questions question0_ 
    where
        question0_.id=?

// Error

2018-11-22 13:07:42.037 ERROR 5692 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->com.example.postgresdemo.model.Answer["question"]->com.example.postgresdemo.model.Question$HibernateProxy$DzJlWmh6["hibernateLazyInitializer"])] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->com.example.postgresdemo.model.Answer["question"]->com.example.postgresdemo.model.Question$HibernateProxy$DzJlWmh6["hibernateLazyInitializer"])

标签: javaspring-bootfetchlazy-loading

解决方案


你有你的问题注释@JsonIgnore,告诉杰克逊不要序列化该值,这就是它丢失的原因。

当您没有错误时,您收到错误的原因@JsonIgnore是因为 JSON 的序列化发生在将引发异常的事务的外部。在序列化之前将问题关系标记为FetchType.EAGER或在事务内部调用answer.getQuestion(),以便获取问题而不是代理。

您还可以注释您的控制器,@Transactional以便序列化发生在事务中。


推荐阅读