返回PagedResource

时间:2018-06-18 13:31:31

标签: java json spring-boot spring-data-rest jackson2

当我从Page<Entity>课程中的方法返回@RestController时,Entity的所有字段都通过@OneToXXX@ManyToXXX引用返回JSON对象。但是,当我将返回类型切换为PagedResource时(为了能够添加响应的链接),根本不包含@ManyToXXX个字段。

以下是有问题的方法:

@GetMapping("/fetch")
public PagedResources getResults(Pageable pageable, PagedResourcesAssembler assembler) {

        Page<ParentClass> page = myRepository.findAll(pageable);

        PagedResources pagedResources = assembler.toResource(page, myResourceAssembler);

        return pagedResources;
}

这是资源汇编程序:它是MyController主体中的@Autowired

MyResourceAssembler

@Component
public class MyResourceAssembler extends ResourceAssemblerSupport<ParentClass, Resource> {
    public MyResourceAssembler() { super(MyController.class, Resource.class); }

    @Override
    public Resource toResource(ParentClass obj) {

        return new Resource<>(obj,
                linkTo(methodOn(MyController.class).getResults(obj.getId())).withRel("edit"),
    }
}

以下是基本的类定义:

ParentClass

@Entity
@Table(name = "parent_table", catalog = "myDB")
public class ParentClass implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @ManyToOne(optional = false)
    @JoinColumn(name = "other_class", referencedColumnName = "id")
    private OtherClass otherClass;

    @OneToOne(mappedBy = "parent")
    private SampleField1 sampleField1;

    @OneToMany(mappedBy = "parent")
    private List<SampleField2> sampleField2;

}

SampleField1 OneToXXX

@Entity
@Table(name = "sample_table_1", catalog = "myDB")
public class SampleField1 implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name="some_field")
    String someField;

    @OneToOne
    @JoinColumn(name = "sample_field_1", referencedColumnName = "id")
    @JsonBackReference //to avoid infinite recursion
    private ParentClass parent;
}

OtherClass ManyToOne

@Entity
@Table(name = "other_table", catalog = "myDB")
public class OtherClass  implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name="some_other_field")
    String someOtherField;

    // I don't need any reference to ParentClass here.
}

要在此处添加更多详细信息,请在changeProperties()类中PersistentEntityJackson2Module方法的日志输出:

s.d.r.w.j.PersistentEntityJackson2Module : Assigning nested entity serializer for @javax.persistence.OneToOne(..) com.project.SampleField1 com.project.model.ParentClass.sampleField1
s.d.r.w.j.PersistentEntityJackson2Module : Assigning nested entity serializer for @javax.persistence.OneToMany(..)  com.project.SampleField2 com.project.model.ParentClass.sampleField2
// .... omitted other lines for brevity

生成的JSON是:

{
   "_embedded":{
      "parentClasses":[
         {
            "id":1,
            // <-- There is no field for otherClass !
            "sampleField1":{
               "id":1,
               "sampleField":"blabla"
            },
            "sampleField2":[ ]
         }
      ]
   },
   "links":[

   ]
}

如上所示,OneToXXX字段被视为序列化,但ManyToOne字段没有输出 Assigning nested entity serializer for @javax.persistence.ManyToOne ... com.my.OtherClass ...因此在响应JSON中不存在。

根据this SO answer@ManyToXXX引用的实体被附加为JSON响应的链接。但这对我来说不是一个可接受的解决方案,因为我对其他客户有不同的消费计划。

Bottomline,我希望从ManyToOne方法返回我的JSON响应中的getResults()个引用实体。

我能提供的任何内容只需在评论中提出。

1 个答案:

答案 0 :(得分:1)

在响应中返回实体不是最好的方法,因为通常客户不需要整个数据集。此外,如果实体之间具有彼此的链接,则在序列化尝试时将导致StackoverflowException。使用DTO进行响应。至少它将帮助您确定问题出在哪里-序列化或从数据库中获取。无论如何,这是将数据提供给客户端的更合适的方法。

顺便检查一下ParentClass中otherClass的getter和setter :)如果threre不是getter和setter,那将是您遇到问题的原因。

此外,请查看OtherClass作为默认的空构造函数。如果没有,请添加它。