当我从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()
个引用实体。
我能提供的任何内容只需在评论中提出。
答案 0 :(得分:1)
在响应中返回实体不是最好的方法,因为通常客户不需要整个数据集。此外,如果实体之间具有彼此的链接,则在序列化尝试时将导致StackoverflowException。使用DTO进行响应。至少它将帮助您确定问题出在哪里-序列化或从数据库中获取。无论如何,这是将数据提供给客户端的更合适的方法。
顺便检查一下ParentClass中otherClass的getter和setter :)如果threre不是getter和setter,那将是您遇到问题的原因。
此外,请查看OtherClass作为默认的空构造函数。如果没有,请添加它。