【问题标题】:Spring rest producing duplicate jsonSpring rest产生重复的json
【发布时间】:2016-02-15 15:01:35
【问题描述】:

我正在尝试一个简单的问答应用程序,它包含三个类 Quiz、Question 和 Answer。基本关系如下:

@Entity
public class Quiz {

    @Id
    @GeneratedValue

    private Long id; 

    private String description;

     @OneToMany(cascade=CascadeType.PERSIST, fetch=FetchType.EAGER)
     private List<Question> questions = new ArrayList<>();

@Entity
public class Question {

    @Id
    @GeneratedValue

    private Long id;

    private String description;

    @ElementCollection(fetch=FetchType.EAGER)
    private List<Answer> answers;

@Embeddable
public class Answer {


    private String description;
    private boolean correct;

JPA/数据库已正确加载,其中包含一个问题和三个答案的单个测验。但是,返回的相应 JSON 有很多重复数据。

{
  "id" : 1,
  "description" : "Intro to Spring 4",
  "questions" : [ {
    "id" : 1,
    "description" : "What is Spring?",
    "answers" : [ {
      "description" : "A season",
      "correct" : false
    }, {
      "description" : "A coily wire",
      "correct" : false
    }, {
      "description" : "A wonderful framework",
      "correct" : true
    } ]
  }, {
    "id" : 1,
    "description" : "What is Spring?",
    "answers" : [ {
      "description" : "A season",
      "correct" : false
    }, {
      "description" : "A coily wire",
      "correct" : false
    }, {
      "description" : "A wonderful framework",
      "correct" : true
    } ]
  }, {
    "id" : 1,
    "description" : "What is Spring?",
    "answers" : [ {
      "description" : "A season",
      "correct" : false
    }, {
      "description" : "A coily wire",
      "correct" : false
    }, {
      "description" : "A wonderful framework",
      "correct" : true
    } ]
  } ]
}

有人看到明显的东西吗?我正在使用 Jackson 映射器。

【问题讨论】:

  • 我感觉您的 JPA 执行 JOIN 导致 3 行的问题与您的 3 个答案相同...您可以分享用于输出该 JSON 的代码吗?
  • 实际上,我使用的是 Spring CrudRepository,所以我唯一的代码是这个控制器方法 @RequestMapping("quizzes/{id}") public Quiz quiz(@PathVariable Long id){ return quizRepository.findOne( ID); }

标签: json spring rest duplicates


【解决方案1】:

您应该使用Set 而不是List 来提问和回答。此外,您的实体应覆盖equals()hashCode(),以便它们通过id 属性实现相等性。

至于列表包含重复项的原因,an explanation is given here。简而言之,它表明向数据库发出了 SQL 外连接,而外连接确实会产生重复的结果。

摘录:

首先,您需要了解 SQL 以及 OUTER JOIN 在 SQL 中的工作原理。如果您不完全理解和理解 SQL 中的外连接,请不要继续阅读此常见问题解答项目,而应查阅 SQL 手册或教程。否则你将无法理解下面的解释,你会在 Hibernate 论坛上抱怨这种行为。

(...)

想知道为什么会有重复项吗?查看 SQL 结果集,Hibernate 并没有在外连接结果的左侧隐藏这些重复项,而是返回驱动表的所有重复项。如果您在数据库中有 5 个订单,并且每个订单有 3 个订单项,那么结果集将是 15 行。这些查询的 Java 结果列表将有 15 个元素,所有类型均为 Order。 Hibernate 将仅创建 5 个 Order 实例,但 SQL 结果集的副本被保留为对这 5 个实例的重复引用。如果您不理解最后这句话,则需要阅读 Java 以及 Java 堆上的实例与对此类实例的引用之间的区别。

虽然链接和说明适用于 Hibernate,但使用 JPA 可以观察到相同的行为。

【讨论】:

    【解决方案2】:

    在 getter 方法中注入 @JsonProperty("yourFiledName") 对我有用。

    @Entity
    public class Quiz {
    
        @Id
        @GeneratedValue
    
        private Long id; 
    
        private String description;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
       @JsonProperty("description")
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    

    /** 对问题实体类做同样的事情 **/

    注意:来自 Jackson 库的 @JsonPropertiy。对于maven用户,下面是依赖项

           <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.9.6</version>
            </dependency>
    

    【讨论】:

    • 它对我有用,但有人可以解释一下这背后的逻辑吗?提前致谢。
    【解决方案3】:

    只为那些在这个问题上苦苦挣扎的人。刚设置 @ElementCollection(fetch=FetchType.EAGER)@ElementCollection(fetch=FetchType.LAZY)

    这解决了我的问题!

    【讨论】:

      猜你喜欢
      • 2015-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多